blinkfox / fenix

This is an extension library to the Spring Data JPA complex or dynamic SQL query. 这是一个比 MyBatis 更加强大的 Spring Data JPA 扩展库,为解决复杂动态 JPQL (或 SQL) 而生。https://blinkfox.github.io/fenix
https://blinkfox.github.io/fenix
Apache License 2.0
346 stars 72 forks source link

关于调用 andIn() 时传入空数组的问题 #48

Closed lanyuanxiaoyao closed 3 years ago

lanyuanxiaoyao commented 3 years ago

你好, 我发现使用andIn(name, list)传入空数组的时候, 会构造永真条件where 1 = 1, 即查询全部, 但是使用 sql 查询的时候select * from xxx where name in ()时, 返回结果为空, 似乎两边逻辑不相符, 期望的是传入空数组的情况下返回结果为空, 不知道这点是否是专门设计的?

blinkfox commented 3 years ago

是的,传入空的话,会认为是不需要此匹配条件,会跳过生成此 SQL,你可以加 match 匹配规则,去判断是否生成。

lanyuanxiaoyao commented 3 years ago

是的,传入空的话,会认为是不需要此匹配条件,会跳过生成此 SQL,你可以加 match 匹配规则,去判断是否生成。

match 只能决定是否生成这个条件, 但是在生成这个条件的时候, 如果传入空 list, 就变成查询全部, 这个「参数为空就查询全部」的默认方式和直觉不一样.

用 JPA 的 Specification 写的时候是遵守 sql 的形式, builder.in(root.get("xxx")).value(emptyList())会生成where xxx in (), 尽管 sql 执行会报错, 但是符合 sql 规则.

我在实际开发的时候, 认为andIn和 Specification 逻辑相同, 所以只对 list 是不是为 null 做了判断, 但是没有额外判断 list 是否为空, 如果 sql 执行抛异常会有统一处理, 但现在直接返回全部内容让前端做删除动作的时候, 将所有数据都删掉了, 所以我理解是逻辑和 Specification 一致可能会比较好, 哪怕传入空 list 就1=0也可以避免一些误用.

blinkfox commented 3 years ago

嗯,理解你的意思。早先这个功能机制是以“多条件模糊查询”来做的,如果不传这个字段,意味着,不以该字段作为查询字段,其实就是不生成这个 SQL,所以就会有这个现象,所以,你最好加 isEmpty 的 match ,而不是 nullmatch 条件。

lanyuanxiaoyao commented 3 years ago

嗯,理解你的意思。早先这个功能机制是以“多条件模糊查询”来做的,如果不传这个字段,意味着,不以该字段作为查询字段,其实就是不生成这个 SQL,所以就会有这个现象,所以,你最好加 isEmpty 的 match ,而不是 nullmatch 条件。

我理解这个作为「where 条件构造器的用意」, 但传空的 list 和不传是两回事, 如果是 null 可以理解为不符合「in 一个集合」的逻辑而去掉, 但是空的 list 是常见的, 有值没值都传一个 list 可以简单地避免空指针, 至于怎么对待这个 list, 应该交给数据库处理, 比如在 mysql 里in ()会报错, h2 里in ()返回空数据, 也就是说在 h2 里, in 一个空的 list 是有意义的, 不应该直接去掉.

blinkfox commented 3 years ago

在大多数实际场景中,空和 null 都是无的意思,Fenix 中直接会视为无效,不会去拼接这个无意义的 SQL 的。这个逻辑为了向前兼容,后续也是不会再修改这个逻辑的。

lanyuanxiaoyao commented 3 years ago

在大多数实际场景中,空和 null 都是无的意思,Fenix 中直接会视为无效,不会去拼接这个无意义的 SQL 的。这个逻辑为了向前兼容,后续也是不会再修改这个逻辑的。

感谢解答, 空 list 和 null 肯定是不一样的, 集合里面没有东西是有含义的, 接口里面为了避免 null, 使用空 list 来作为参数很常见, 有没有东西都有一个 list 做参数; 抛去这一点来说, fenix 既然扩展了 jpa 的一些操作, 那么起码逻辑和 Specification 保持一致会比较重要, 这也是最开始会让我觉得疑惑的地方, 同样的查询条件和逻辑, Specification 原样生成 sql, fenix 则忽略了; 希望接口设计在这点上, 可以多考虑一下吧, 如果是作为一个 feature 的话, 也希望有更明显一点的提示, 比如多加一个参数或使用两个方法来区别开来.