In my spring-boot application (using hibernate), for simple CRUD on entities I have a generic DAO implementation with create, update, read, delete methods. My question is specifically around the read functionality - where I cannot use the generic read method on entities which have relationship. As doing so in the generic DAO implementation the child objects(configured with lazy-loading) too get populated.
GenericHibernateDaoImpl.java
public class GenericHibernateDaoImpl<T, PK extends Serializable> implements IGenericDao<T,PK>{
// including only my read method
@Override
public T read(Class<T> t, int id) {
String _query = String.format("SELECT r FROM %s r WHERE Id= %s",t.getName(),""+id);
return (T) getSession().createQuery(_query, t).getSingleResult();
}
}
The above helps me when I want to query simple tables with no relationship.
In scenarios where I want to select a database record without loading its children (in cases of 1..M relationship but only returning the parent), I use a non-generic type as below (because if I use the above class in such case, it pulls all data from associated tables):
SalePlanDao.java - here I can get just the parent record
public class SalePlanDao implements IGenericDao<FFMSalePlan, Serializable> {
@Override
public FFMSalePlan read(Class<FFMSalePlan> t, int id) {
String _query = String.format("SELECT r FROM %s r WHERE Id= %s",t.getName(),""+id);
FFMSalePlan _mmSalePlan = (FFMSalePlan) getSession().createQuery(_query, t).getSingleResult();
return _mmSalePlan;
}
}
When I call the SalePlanDao.read, it now returns only the parent record and not its children (lazy-loading).
I want to be able to load only the parent entity like in snippet 2 from a generic read method like in GenericHibernateDaoImpl.java. That way, I can keep 1 such method in the whole project and only when children are needed, invoke a separate DAO which has a call to Hibernate.Initialize(etc).
I am assuming that the field on which lazy-load is enabled is "touched" in the generic implementation and hence it invokes selects on the child tables also.
My question is more of "how to design it" rather than any technical issue/error I am facing. How do I achieve generic read on entities with relationship to only return the parent record?
Entities
FFMSalePlan.java
public class FFMSalePlan implements Serializable {
//other fields
@JsonProperty("detail")
@OneToMany(mappedBy = "mSalePlan", orphanRemoval = true)
@Cascade({CascadeType.ALL})
private Set<FFTSalePlan> tSalesPlan;
}
FFTSalePlan.java
public class FFTSalePlan implements Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "i_saleplan_id", referencedColumnName = "i_id" )
private FFMSalePlan mSalePlan;
}
If I were you, I wouldn't write generic logic or use Hibernate.initialize
to initialize relationships. Usually, the way to go is using entity graphs in a Spring Data repository: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.entity-graph
Another way to handle the fetching is to make use of DTOs or projections. You can look into Spring Data Projections, but I think this is a perfect use case forBlaze-Persistence Entity Views , which is similar to Spring Data Projections, but goes way beyond the basic stuff and performs a lot better.
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.