java 方法命名中的 Spring 'NOT IN' 没有按预期工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33271099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring 'NOT IN' in method naming does not work as it expected
提问by Oleh Dokuka
Question
问题
Is it bug, or it just my fail? Can you explain me what is wrong?
是bug,还是我的失败?你能解释一下有什么问题吗?
Code
代码
I have created simple JPARepository
我创建了简单的JPARepository
@Repository
interface UserRepository extends JpaRepository<User, Long> {
User findByName(String name);
Collection<User> findByIdNotIn(Collection<Long> users);
}
It looks correct. And it works correct if users
is not empty. But otherwise it works incorrect:
看起来是正确的。如果users
不为空,它就可以正常工作。但否则它工作不正确:
result = userRepository.findByIdNotIn([]);
It returns empty result, but it should be equals to result of findAll
method call.
它返回空结果,但它应该等于findAll
方法调用的结果。
userRepository.findByIdNotIn([]).equals(userRepository.findAll());
Also
还
To check result I have added @Query
annotation to method
为了检查结果,我@Query
在方法中添加了注释
@Repository
interface UserRepository extends JpaRepository<User, Long> {
User findByName(String name);
@Query('SELECT u FROM User u WHERE u.id NOT IN ?1')
Collection<User> findByIdNotIn(Collection<Long> users);
}
And in this case expected result was correct.
Also I have tried write query using native Hibernate CriteriaBuilder
在这种情况下,预期结果是正确的。我也尝试过使用本机 Hibernate 编写查询CriteriaBuilder
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = builder.createQuery(User.class);
Root<User> root = query.from(User.class);
query.where(builder.not(root.get("id").in([])));
result = entityManager.createQuery(query.select(root)).getResultList();
And in this case expected result was correct too.
在这种情况下,预期结果也是正确的。
Additional Info
附加信息
Result Hibernate queries:
Correct result (using @Query
annotation):
结果 Hibernate 查询:正确的结果(使用@Query
注释):
Hibernate: select user0_.id as id1_7_, user0_.name as name2_7_ from User user0_ where user0_.id not in ()
Incorrect result(using method naming):
结果不正确(使用方法命名):
Hibernate: select user0_.id as id1_7_, user0_.name as name2_7_ from User user0_ where user0_.id not in (?)
My conclusion
我的结论
It looks like a Spring JPA bug
它看起来像一个 Spring JPA 错误
New Additional Info
新的附加信息
I spent a day in debuging spring-data-jpa
source code, and I found that the problems occurs in org.springframework.data.jpa.provider.PersistenceProvider
in method potentiallyConvertEmptyCollection
for HIBERNATE
调试了一天spring-data-jpa
源码,发现问题出在org.springframework.data.jpa.provider.PersistenceProvider
in method potentiallyConvertEmptyCollection
for HIBERNATE
@Override
public <T> Collection<T> potentiallyConvertEmptyCollection(Collection<T> collection) {
return collection == null || collection.isEmpty() ? null : collection;
}
When collection is empty this function return null
value.
But I have found, if this value replaced (at runtime) on empty collection again then the final result would be correct!!!
当集合为空时,此函数返回null
值。但我发现,如果这个值再次替换(在运行时)空集合,那么最终结果将是正确的!!!
HAVE YOU ANY IDEA ABOUT THIS?!
你对这个有什么想法吗?!
采纳答案by TheBakker
From JPA Specification 4.6.9 In Expressions :
从 JPA 规范 4.6.9 在表达式中:
There must be at least one element in the comma separated list that defines the set of values for the IN expression. If the value of a state_field_path_expression or in_item in an IN or NOT IN expression is NULL or unknown, the value of the expression is unknown.
逗号分隔列表中必须至少有一个元素来定义 IN 表达式的值集。如果 IN 或 NOT IN 表达式中 state_field_path_expression 或 in_item 的值为 NULL 或未知,则表达式的值未知。
So Spring JPA is just following JPA specification, even if, as you said, one could expect that there would be no restriction.
因此,Spring JPA 只是遵循 JPA 规范,即使如您所说,人们可以预期不会有任何限制。
Best to just do the check in your business before calling the right repository method.
最好在调用正确的存储库方法之前检查您的业务。