By the way, you can choose to use my framework to do resolve your problem perfectly if you can accept it
Goto https://github.com/babyfish-ct/babyfish to get it,
A functionality called "QueryPath" can resolve your problem perfectly, please view babyfishdemo-spring/../QueryPathTest.java.
OK, Let's discuss your problem, suppose you want to handle all the 3 types of lazy properties supported by ORM:
lazy collection property, lazy reference property and lazy basic property(lazy basic property need bytecode instrument)
(1) Declare JPA Entity class(Also please use the bytecode instrument task of babyfish in the pom.xml)
Code:
@JPAObjectModelInstrument
@Entity
@Table(...)
public class TestPersonaMutua {
@Id
@Column(name = "ID")
private Long id;
// (1) Lazy ManyToOne, let it to be lazy explicit, because LAZY is not default
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "BOSS_ID")
private TestPersonaMutua boss;
// (2) Lazy OneToMany, LAZY is default
@OneToMany(mappedBy = "boss")
private Set<TestPersonaMutua> employees;
// (3) Lazy Basic, supported since Hibernate3, need byte-code instrument.
@Basic(fetch = FetchType.LAZY)
@Lob
@Column(name = "IMAGE")
private byte[] image;
@Column(...) //Simple property
private String name;
...getters/setters...
}
(2) Declare the DAO
Code:
@org.springframework.streotype.Repository
public class TestPersonaMutuaDAO {
@javax.persistence.PersistenceContext
private org.babyfish.persistence.XEntityManager em; //extends javax.persistence.EntityManager
// The class "TestPersonaMutua__" whose name ends with TWO(not one) underlines
// is the typed query path model class whose source code is generated by the Maven plugin of babyfish
public List<TestPersonaMutua> getTestPersonaMutuas(
String likeName,
// 0..any queryPaths, should be specified by UI layer
// then send it to business logic layer(locally or remotely)
// finally send it to data access layer(locally or remotely)
TestPersonaMutua__ ... queryPaths
) {
return this
.em
.createQuery("from TestPersonaMutua p where p.name like :likeName", TestPersonaMutua.class)
.setParemeter("likeName", likeName)
.setQueryPaths(queryPaths) //Use queryPaths here
.getResultList();
}
}
(3) Default query without queryPaths, only query the TestPersonaMutua it self
Code:
List<TestPersonaMutua> testPersonaMutuas = testPersonaMutuaDAO.getTestPersonaMutuas("A");
Only one simple SQL is generated:
Code:
SELECT p.* from TEST_PERSON_MUTUA p where p.NAME like ?
(4) Resolve your problem,
Use FetchPath to fetch all the lazy collection, lazy reference and lazy baisc properties
Code:
List<TestPersonaMutua> testPersonaMutuas = testPersonaMutuaDAO.getTestPersonaMutuas(
"A",
// Fetch @ManyToOne for two levels, by adding fetch dynamically
TestPersonaMutua__.begin().boss().boss().end(),
// Fetch @OneToMany for two levels, by adding fetch dynamically
TestPersonaMutua__.begin().employees().employees().end(),
// Fetch @Basic(fetch = FetchType.LAZY), by generating new SQL statement
TestPersonaMutua__.begin().image().end(), //Fetch @Basic
);
Two SQL statments are generated,
The first one is used to Query the data and fetch associations
Code:
SELECT p.*
from TEST_PERSON_MUTUA p
left join TEST_PERSON_MUTUA boss
on p.BOSS_ID = boss.ID // fetch boss
left join TEST_PERSON_MUTUA bossBoss
on boss.BOSS_ID = bossBoss.ID //fetch boss.boss
left join TEST_PERSON_MUTUA employees
on p.ID = employees.BOSS_ID // fetch employees
left join TEST_PERSON_MUTUA employeesEmployees
on employees.ID = employeesEmployees // fetch employees.employees
where p.NAME like ?
The second one is used Fetch the @Basic(fetch = FetchType.LAZY) properties
Code:
SELECT p.ID, p.IMAGE
from TEST_PERSON_MUTUA
where p.ID in (?, ?, ?, ?...?)
(5) DynamicSorting
Code:
List<TestPersonaMutua> testPersonaMutuas = testPersonaMutuaDAO.getTestPersonaMutuas(
"A",
TestPersonaMutua__.begin().boss().boss().end(), //Fetch @ManyToOne
TestPersonaMutua__.begin().employees().employees().end(), //Fetch OneToMany
TestPersonaMutua__.begin().image().end(), //Fetch @Basic(fetch = FetchType.LAZY),
// Query result itself should be order by name asc
TestPersonaMutua__.preOrderBy().name().asc(),
// The collection association "this.employees" should be order by name desc
TestPersonaMutua__.preOrderBy().employees().name().desc(),
TestPersonaMutua__.preOrderBy().employees().employees().name().desc()
);