春天不在'在方法命名中不能按预期工作

时间:2015-10-21 23:41:26

标签: java spring hibernate spring-boot spring-data-jpa

问题

是错误,还是我的失败?你能解释一下我的错误吗?

代码

我创建了简单的 JPARepository

@Repository
interface UserRepository extends JpaRepository<User, Long> {
    User findByName(String name);


    Collection<User> findByIdNotIn(Collection<Long> users);
}

看起来很正确。如果users不为空,它的工作正确。但否则它的工作原理不正确:

result = userRepository.findByIdNotIn([]);

它返回空结果,但它应该等于findAll方法调用的结果。

userRepository.findByIdNotIn([]).equals(userRepository.findAll());

另外

要检查结果,我已将@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);
}

在这种情况下,预期结果是正确的。 此外,我尝试使用本机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();

在这种情况下,预期结果也是正确的。

其他信息

结果Hibernate查询: 正确的结果(使用@Query注释):

Hibernate: select user0_.id as id1_7_, user0_.name as name2_7_ from User user0_ where user0_.id not in  ()

结果不正确(使用方法命名):

Hibernate: select user0_.id as id1_7_, user0_.name as name2_7_ from User user0_ where user0_.id not in  (?)

我的结论

它看起来像是一个Spring JPA bug

新增附加信息

我花了一天的时间来调试spring-data-jpa源代码,我发现问题出现在方法org.springframework.data.jpa.provider.PersistenceProvider的{​​{1}}中 HIBERNATE < /强>

potentiallyConvertEmptyCollection

当集合为空时,此函数返回@Override public <T> Collection<T> potentiallyConvertEmptyCollection(Collection<T> collection) { return collection == null || collection.isEmpty() ? null : collection; } 值。 但我发现,如果再次在空集合中替换此值(在运行时),那么最终结果将是正确的!

你有什么想法吗?!

1 个答案:

答案 0 :(得分:5)

来自JPA规范4.6.9表达式:

  

逗号分隔列表中必须至少有一个元素定义IN的值集   表达。   如果IN或NOT IN表达式中state_field_path_expression或in_item的值为NULL或   未知,表达的价值是未知的。

所以Spring JPA只是遵循JPA规范,即使如你所说,人们可以预期不会有任何限制。

最好在调用正确的存储库方法之前检查您的业务。