We are using Spring Data (version 1.3.2) with OpenJPA (version 2.2.2) in our project. We are facing issue with lazily loaded fields in our entities for OneToOne relationship. I will describe the issue with an example:
We have two entities (say Person and Address). There is one to one relationship between Person and Address. Below given is the code sample for Person and Address entity (getters and setters left out for brevity):
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String firstName;
private String lastName;
@OneToOne(mappedBy = "person", fetch = FetchType.LAZY)
private Address address;
}
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String streetAddress;
private String city;
private String zipCode;
@OneToOne
@JoinColumn(name="PERSON_ID")
private Person person;
}
We then created AddressRepository and PersonRepository by extending from JpaRepository to provide us the basic CRUD operations for these two entities.
In our application Person entity is created first without having any address associated with it. Address entity is then created at a later point in time by setting appropriate Person entity in Address instance. Until this point all works as expected.
Now if query Person entity using PersonRepository's findOne method by passing appropriate id then the returned Person instance does not have address field populated. When we access address field of Person that is returned by PersonRepository it happens to be null. We were expecting that address field in Person would be available if there is an Address entity associated with Person. Given that the fetch type is set to LAZY would just mean that it would be loaded only when we try to access address field. This is how indeed it works when we use JPA APIs directly (using EntityManager.find() method).
This same piece of code used to work fine when we were using hibernate. Due to some legal reasons we had to change our JPA provider to OpenJPA and this stopped working. Is there anything that we should do differently when using OpenJPA in order to get lazy loading of OneToOne working?
Note: We have L2 cache turned ON. We found out that there is an issue with L2 cache in OpenJPA and opened this defect on OpenJPA (https://issues.apache.org/jira/browse/OPENJPA-2522). However, even with this defect there is a workaround (evicting the entity from L2 cache using entitymanagerfactory's evict method) and using JPA APIs we can get it to work. However, with spring data we observed that this issue exists even when we use this workaround. We did this by providing entity-manager-factory-ref in jpa-repositories and then injecting same emf in our beans to evict the entity from cache:
<jpa:repositories base-package="com.abc.dsp.spring.data.repository" entity-manager-factory-ref="emf"/>
Due to widespread use of spring data in our project it is difficult to move to using pure JPA APIs. Also, like mentioned in some answers here and here we are trying to avoid to changing to eager fetch type or custom setter methods due to widespread code impact.
UPDATE: Using custom setter method is also not working. What is working is changing the fetch type to EAGER. However, we would like to keep fetchType to LAZY because in most cases we don't need the associated object and that object is quite heavy.