在EJB3 QL中,left join 与left join fetch都是用来join查询,但是它们不同之处在于 left join fetch可以用来把lazy装载的关联数据load到查询的对象中去。除此之外,还有其它需要注意的地方。如下面的例子:
实体类定义:
@Entity(name="JobInfo") public class JobInfo implements Serializable { @OneToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE}, fetch=FetchType.LAZY, mappedBy="jobInfo") @Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN }) private Set<JobRunInfos> jobRunInfos = new HashSet<JobRunInfos>();
@ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="CREATOR",nullable=false) private SysUser creator;@ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="EXCUTOR",nullable=false) private SysUser excutor;EJB3 QL语句:
"SELECT jobInfo FROM JobInfo jobInfo LEFT JOIN FETCH jobInfo.creator LEFT JOIN FETCH jobInfo.executor LEFT JOIN jobInfo.jobRunInfos jobRunInfos " + " WHERE (" + "(jobInfo.createDate>=?1 AND jobInfo.createDate<=?2) OR " + "(jobRunInfos.entryDate>=?1 AND jobRunInfos.entryDate<=?2) OR " + "(jobRunInfos.executeDate>=?1 AND jobRunInfos.executeDate<=?2))";
- creator和executor因为是Lazy load的所以需要用LEFT JOIN FETCH,否则在最终查询出来的DAO对象 JobInfo中它们是不可用的。
- 并不是非得用了LEFT JOIN FETCH某个Lazy对象之后,在where子句中才可以使用该对象的引用。如jobRunInfos在where子句中,jobRunInfos.entryDate对其加以了引用。
又如:
"SELECT jobInfo FROM JobInfo jobInfo LEFT JOIN jobInfo.jobRunInfos jobRunInfos " + " WHERE (" + "(jobInfo.creator.id=?1) OR " + "(jobRunInfos.entryDate>=?2 AND jobRunInfos.entryDate<=?3) OR " + "(jobRunInfos.executeDate>=?2 AND jobRunInfos.executeDate<=?3))";尽管它没有显示地FETCH,我们仍可在上面的where子句中引用它。如:jobInfo.creator.id=?1这句引用是正确的3. 在where语句中,可以使用集合类来引用它个体类的属性。如 jobRunInfos.entryDate,尽管entryDate是属于JobRunInfo这个类的,但仍可以用它的集合类形式来引用它。这个没有错,除了看上去有点怪之外!
4. 如果一个集合类被LEFT JOIN FETCH,那么它的个体类一定要出现在 select 语句之后,否则就会报fetch special exception.。如:上面的查询改成:"SELECT jobInfo FROM JobInfo jobInfo LEFT JOIN FETCH jobInfo.jobRunInfos jobRunInfos " 那么就会报错。