Is it bug, or it just my fail? Can you explain me what is wrong?
I have created simple 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:
result = userRepository.findByIdNotIn([]);
It returns empty result, but it should be equals to result of findAll
method call.
userRepository.findByIdNotIn([]).equals(userRepository.findAll());
To check result I have added @Query
annotation to method
@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
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.
Result Hibernate queries:
Correct result (using @Query
annotation):
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 (?)
It looks like a Spring JPA bug
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
@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!!!
From JPA Specification 4.6.9 In Expressions :
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.
So Spring JPA is just following JPA specification, even if, as you said, one could expect that there would be no restriction.
Best to just do the check in your business before calling the right repository method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With