Skip to content
Advertisement

Spring Data JPA: What is wrong or how to correct this jpql query

The entity relationships are – A student belongs to one college And a college can have multiple students. So there is ManyToOne relationship between Student –> College And a OneToMany relationship between College –> Student.

The entities are as below.

JavaScript

and

JavaScript

1) I am using the below jpql query in spring data jpa repository.

JavaScript

I am expecting that a list with single college entity to be returned as collegeId is primary key for the College Entity and I am giving only one id for the IN. But What I am getting is a list of colleges all with same primary key (collegeId=2). The size of returned list is equal to the number students in the college.

JavaScript

And for

JavaScript

output:
College [collegeId=2, collegeName=college2]
College [collegeId=2, collegeName=college2]
College [collegeId=2, collegeName=college2]
College [collegeId=2, collegeName=college2]
College [collegeId=2, collegeName=college2]
College [collegeId=2, collegeName=college2]

2) Another issue i noticed,
calling collegeRepo.findByCollegeIdsJPQL() for second time is causing another sql query ie DB hit. Can not this be served from session(first level) cache. I have annotated the calling method with

JavaScript

output log –

JavaScript

Advertisement

Answer

(1) Because LEFT JOIN will return the combination of a college and its student. So if a college has N students , N records will be returned. You have to add DISTINCT to remove the duplication :

JavaScript

However, it will cause the generated SQL has distinct keyword which may has performance impact. So since Hibernate 5.2, they provides a query hint called hibernate.query.passDistinctThrough which can configure not to add distinct keyword in the generated SQL and Hibernate will help to remove the duplication instead :

JavaScript

For details , please see this blog post.

(2) It is normal. You have to configure 2nd level cache and query cache to prevent another DB hit. 1st level cache mainly works when getting an entity by ID using EntityManager#get() in the same transaction. It does not work when using JPQL query.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement