I'm currently trying to evaluate the possibilies of using Spring Data JPA.
Trying to use Projections, I'm currently stuck in trying to fetch specific properties Eager.
I have a simple entity which lazy references another entity with a foreign key. I now would like to define different projections for the prior entity. "Primitive" properties are projected well into the projection interface, but trying to project another entity/projection results in it still being lazy loaded.
I would now like to tell Spring/JPA to eagerly load entities/projections inside projections. One possible way would be to use EntityGraphs (They were working well), but I would have to create repositories for each method using different graphs. Question being which other ways are there?
Example:
Entity Buyer:
@Entity
public class Buyer {
private Integer id;
private String someProperty;
private User user;
...
@OneToOne(
fetch = FetchType.LAZY)
@JoinColumn(
name = "CAB_USR_ID",
referencedColumnName = "ID",
updatable = false,
nullable = true,
foreignKey = @ForeignKey(name = "FK_CAB_USR"))
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Entity User:
@Entity
public class User {
private Integer id;
private String name;
...
}
Projection Buyer
public interface BuyerCProjection {
Integer getId();
UserProjection getUser();
}
Projection User
public interface UserProjection {
Integer getId();
String getName();
}
Repository I would like to use
public interface BuyerRepository extends Repository<Buyer, Integer> {
<T> List<T> findBy(Class<T> t);
}
With a LAZY type dependency, only data of the wanted object is loaded: author's data is not retrieved. With Spring Data JPA, every relationship between 2 domain objects owns one of these data loading types. By default, the method will be determined by the relationship type.
By default, JPA uses the lazy fetch strategy in associations of type @ElementCollection. Thus, any access to the collection in a closed Persistence Context will result in an exception. This test throws an exception when we try to access the phone list because the Persistence Context is closed.
By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.
Spring data REST Projection supports projecting only a selected fields from an entity representation. To do that, we can define those specific fields into our @Projection interface. Let's create a custom view of our Student entity with first name and last name fields.
I don't think there is a way to instruct JPA/Hibernate to fetch eagerly using projections. The projection is applied after the fetch query is executed, so it's too late to modify the query.
There's a compromise solution using the jackson-datatype-hibernate module with the FORCE_LAZY_LOADING
feature enabled. This forces all lazy-loaded objects in your projections to be initialized and returned.
Note that this isn't as efficient as writing custom queries using entity graphs or JOIN FETCH
. It will behave the same as calling Hibernate.initialize
on each lazy-loaded object, executing another select query. So it results in N+1 selects. But it can be a good way to get started. When something starts to be slow, you can still optimize by writing join-fetch or entity graph queries.
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