1

I have one to one unidirectional mapping. I am explicitly fetching both data using 'left join fetch'. Yet, when I run the query, hibernate runs 2 queries. Why?

public class Person {
    @Id
    private Long personId;

    @OneToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="address_id", referrencedColumnName="address_id")
    private Address address;
}

public class Address {
    @Id
    @Column(name="address_id", nullable=false)
    private Long addressId
}

public interface PersonRepository extends JpaRepository<Person, Long> {
    @Query(value="select p from Person p left join fetch p.address where p.personId = :personId")
    Person getPerson(@Param("personId") Long personId)
}

@DataJpaTest
@RunWith(SpringRunner.class)
public class PersonTest {
    @Autowired
    private PersonRepository repo;
    @Test
    public void test() {
        Person person = repo.getPerson(1l);
    }
}

When I run the above test, it runs 2 queries.

1. select * from Person p left join address a on p.address_id=a.address_id where p.person_id=?

2. select * from address a where a.address_id=? -- why is this run?

Why is it running the second query when it's lazily fetched and I am explicitly fetching it in my query?

If you see some typos, it's because I had to rename classes and type them manually.

Another post with somewhat similar issue was offered as a solution to this. But that doesn't solve the issue.

  1. I have set the relationship as lazy
  2. I am explicitly fetching the associated data
  3. It does not have N+1 issue, as this is a one to one relationship
Nero
  • 422
  • 8
  • 22
  • Does this answer your question? [Why does Hibernate execute multiple SELECT queries instead of one when using @Fetch(FetchMode.JOIN)](https://stackoverflow.com/questions/27935761/why-does-hibernate-execute-multiple-select-queries-instead-of-one-when-using-fe) - focus on the "transient children" discussion the accepted answer. – Randy Casburn Feb 03 '22 at 16:04
  • @RandyCasburn similar issue of unwanted queries but I have my code set up as some of the answers have said to do – Nero Feb 03 '22 at 16:15
  • Yes, I do see that. I suspect the second query happens when you access the the `address` of the `person`. That's the way Lazy works in Hibernate. Try using `@Cache` and see if that second query goes away. – Randy Casburn Feb 03 '22 at 16:32
  • can you show your calling code which causes the queries? And why is it possible to omit the `@Param` annotation for the name query parameter? (I'd expect a "org.springframework.dao.InvalidDataAccessApiUsageException: For queries with named parameters you need to use provide names for method parameters.") – fladdimir Feb 03 '22 at 18:24
  • 1
    @fladdimir I have added the calling method which is a test code. I missed typing the "@param" . I have now added it above – Nero Feb 03 '22 at 19:07
  • in your test you are not accessing the lazy `address` property - is the 2nd query for the address still executed? – fladdimir Feb 03 '22 at 19:22
  • (and how is it possible to query with a `String` parameter when the ID type is `Long` ?) – fladdimir Feb 03 '22 at 19:29
  • @fladdimir I am not accessing the lazy address in my test and the 2nd query still runs. String parameter is a typo. I updated it to Long – Nero Feb 03 '22 at 20:16
  • strange, replicating your issue as follows, it does run only a single query. can you spot any setup differences? https://github.com/fladdimir/so-jpa/blob/d23f6c31d671c00191b82ed09ec5c6b92cf4ae15/src/test/java/org/demo/onetoonelazy/OneToOneLazyTest.java#L64 – fladdimir Feb 05 '22 at 11:17

0 Answers0