Hibernate(24): 为什么用DetachedCriteria不能表连接地取数据?
??? HQL到DetachedCriteria的转换?中是项目中实际问题描述, 这里用一个独立的例子来模拟项目中的问题,也基于此做debug跟踪.
?? ? 例子中有两个类: Husband和Wife,在Husband类里对Wife做了OneToOne关联. 代码和基于Annotation的映射配置如下:
@Entitypublic class Husband { @Id @GeneratedValue(strategy= GenerationType.AUTO) private Integer id; private String name; @OneToOne(fetch=FetchType.LAZY) // (1) @JoinColumn(name="wife_id", nullable=false,unique=true) private Wife wife; @Entitypublic class Wife { @Id @GeneratedValue(strategy= GenerationType.AUTO) private Integer id; private String name;???? 更详细的类文件与基于Mysql的建表及数据见附件.
?配置好后, 做如下实验:
??? 1, 直接用如下HQL
?? ???? "select h.wife from Husband h where h.id = :id"
取数据, 没问题,只取出了对应Wife类的信息. Hibernate生成的SQL语句如下:
?? ??? ?? select wife1_.id as id1_, wife1_.name as name1_ from Husbandhusband0_ inner join Wife wife1_ on husband0_.wife_id=wife1_.id wherehusband0_.id=?
??? ?从上面生成SQL来看, Hibernate做了表连接查询,结果集中也只有Wife类信息.
??? 2,? 用如下所示的DetachedCriteria取数据:
?? ???? DetachedCriteria.forClass(Husband.class)
?? ??? ??? ?.add(Property.forName("id").eq(1))
?? ??? ??? ?.setProjection(Property.forName("wife").as("wifeAlias"))
?? ??? ??? ?.setFetchMode("wifeAlias", FetchMode.JOIN)? //(2)
?? ??? ??? ?.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
?? ???? 从运行结果看, 正确的Wife信息取出来了. 不过看相应的SQL,发现有此不对.
?? ???? Hibernate生成并执行的SQL如下:
?? ??? ??? ?select this_.wife_id as y0_ from Husband this_ where this_.id=?
?? ??? ???? select wife0_.id as id1_0_, wife0_.name as name1_0_ from Wife wife0_ where wife0_.id=?
?????? 也就是说, Hibernate并没有做表连接查询,而采用的是二次查询,即从Husband表里得出相应的wifeID,再到Wife表里去取Wife信息. 这样虽说项目中的问题解决了(后来发现并没有解决,详见下一篇:Eclipse的debug欺骗了我), 但与上面红色标志的(2)处的设置不对. (2)处设置的FetchMode为JOIN,为什么不做表连接查询呢?
??? 3, 在上面红色标志(2)处,改为FetchMode.EAGER还是行. 还是二次查询,并没有像用HQL那样一次表连接地取出数据来.
??? 4, 只是作为一种可能性的试试,在上面红色标志(1)处,改为fetch=FetchType.EAGER,与实验3结果一样.
??? 这里把围绕这个问题的实验,记录下来,一是希望引起大家的讨论,二是作为自己的一个备忘并在此基础上做进一步研究.