当前位置:首页 > 开发 > 开源软件 > 正文

hibernate联合查询问题

发表于: 2014-09-04   作者:sxj19881213   来源:转载   浏览:
摘要: 最近在用hibernate做项目,遇到了联合查询的问题,以及联合查询中的N+1问题。 针对无外键关联的联合查询,我做了HQL和SQL的实验,希望能帮助到大家。(我使用的版本是hibernate3.3.2)   1 几个常识:  (1)hql中的几种join查询,只有在外键关联、并且作了相应配置时才能使用。  (2)hql的默认查询策略,在进行联合查询时,会产

最近在用hibernate做项目,遇到了联合查询的问题,以及联合查询中的N+1问题。

针对无外键关联的联合查询,我做了HQL和SQL的实验,希望能帮助到大家。(我使用的版本是hibernate3.3.2)

 

1 几个常识:

 (1)hql中的几种join查询,只有在外键关联、并且作了相应配置时才能使用。

 (2)hql的默认查询策略,在进行联合查询时,会产生N+1问题,即先查询一次得到主键列表,然后根据主键查询N次数据库。

 (3)hibernate有许多优化策略来避免N+1问题,但前提都是外键关联的情况下。

2 基本项目背景

不存在外键关联的几张表,具有各自的主键,需要进行联合查询。示例如下:

      table fare<!--StartFragment--> 

idint(11) NOT NULL PK,

desStnvarchar(255) NULL,

orgStnvarchar(255) NULL

 

      table route

idint(11) NOT NULL PK,

desCodevarchar(255) NULL,

oriCodevarchar(255) NULL

 

fare表和route表是不存在外键关联的,我想利用hibernate进行联合查询,怎么办?

 

3 实验如下

 我首先想到的是,利用HQL进行联合查询,因为可以避免写繁琐的getter和setter方法,如下:

@Test
 public void testHQLSelect() {
       session.beginTransaction();
       List<FareRoute>  list = session.createQuery("select new com.hibernate.FareRoute(f, r) from Fare f,     Route r where f.orgStn=r.oriCode and f.desStn=r.desCode").list();
       for (FareRoute fareRoute : list) {
            System.out.println(fareRoute);
        }
        session.getTransaction().commit();
 }

 

其中,Fare和Route分别是对应于fare表和route表的映射对象,FareRoute是自己定义的引用Fare和Route的类,用于前台显示。

 

这样子,是可以顺利的得到List<FareRoute>的,结果如下:

Hibernate: select fare0_.id as col_0_0_, route1_.routeId as col_1_0_ from Fare fare0_ cross join Route route1_ where fare0_.orgStn=route1_.oriCode and fare0_.desStn=route1_.desCode
Hibernate: select fare0_.id as id23_0_, fare0_.desStn as desStn23_0_, fare0_.orgStn as orgStn23_0_ from Fare fare0_ where fare0_.id=?
Hibernate: select route0_.routeId as routeId24_0_, route0_.desCode as desCode24_0_, route0_.oriCode as oriCode24_0_ from Route route0_ where route0_.routeId=?
Hibernate: select fare0_.id as id23_0_, fare0_.desStn as desStn23_0_, fare0_.orgStn as orgStn23_0_ from Fare fare0_ where fare0_.id=?
Hibernate: select route0_.routeId as routeId24_0_, route0_.desCode as desCode24_0_, route0_.oriCode as oriCode24_0_ from Route route0_ where route0_.routeId=?
Hibernate: select fare0_.id as id23_0_, fare0_.desStn as desStn23_0_, fare0_.orgStn as orgStn23_0_ from Fare fare0_ where fare0_.id=?
Hibernate: select route0_.routeId as routeId24_0_, route0_.desCode as desCode24_0_, route0_.oriCode as oriCode24_0_ from Route route0_ where route0_.routeId=?
Hibernate: select fare0_.id as id23_0_, fare0_.desStn as desStn23_0_, fare0_.orgStn as orgStn23_0_ from Fare fare0_ where fare0_.id=?
Hibernate: select route0_.routeId as routeId24_0_, route0_.desCode as desCode24_0_, route0_.oriCode as oriCode24_0_ from Route route0_ where route0_.routeId=?
Hibernate: select route0_.routeId as routeId24_0_, route0_.desCode as desCode24_0_, route0_.oriCode as oriCode24_0_ from Route route0_ where route0_.routeId=?
Hibernate: select route0_.routeId as routeId24_0_, route0_.desCode as desCode24_0_, route0_.oriCode as oriCode24_0_ from Route route0_ where route0_.routeId=?
Hibernate: select fare0_.id as id23_0_, fare0_.desStn as desStn23_0_, fare0_.orgStn as orgStn23_0_ from Fare fare0_ where fare0_.id=?
Hibernate: select route0_.routeId as routeId24_0_, route0_.desCode as desCode24_0_, route0_.oriCode as oriCode24_0_ from Route route0_ where route0_.routeId=?
Hibernate: select fare0_.id as id23_0_, fare0_.desStn as desStn23_0_, fare0_.orgStn as orgStn23_0_ from Fare fare0_ where fare0_.id=?
Hibernate: select fare0_.id as id23_0_, fare0_.desStn as desStn23_0_, fare0_.orgStn as orgStn23_0_ from Fare fare0_ where fare0_.id=?
Hibernate: select fare0_.id as id23_0_, fare0_.desStn as desStn23_0_, fare0_.orgStn as orgStn23_0_ from Fare fare0_ where fare0_.id=?

1-SHA-BJS-1-SHA-BJS
2-BJS-SHA-2-BJS-SHA
3-BJS-PEK-4-BJS-PEK
5-PEK-SHA-5-PEK-SHA
5-PEK-SHA-6-PEK-SHA
5-PEK-SHA-7-PEK-SHA
7-BBB-AAA-3-BBB-AAA
8-PEK-SHA-5-PEK-SHA
8-PEK-SHA-6-PEK-SHA
8-PEK-SHA-7-PEK-SHA
9-PEK-SHA-5-PEK-SHA
9-PEK-SHA-6-PEK-SHA
9-PEK-SHA-7-PEK-SHA
10-PEK-SHA-5-PEK-SHA
10-PEK-SHA-6-PEK-SHA
10-PEK-SHA-7-PEK-SHA

 

有过项目经验的同学,肯定知道这就是N+1问题,我尝试用left join、设置fetch、修改batch-size等方式进行优化,却由于fare表和route表不存在外键关联,均以失败告终。做了另外一个实验,如下:

 

@Test
 public void testSQLSelect() {
     session.beginTransaction();
     List<Object[]>  list = session.createSQLQuery("select * from fare f, route r where f.orgStn=r.oriCode and f.desStn=r.desCode").addEntity("f", Fare.class).addEntity("r", Route.class).list();
    for (Object[] obj : list) {
        FareRoute fr = new FareRoute((Fare)obj[0], (Route)obj[1]);
        System.out.println(fr);
     }
     session.getTransaction().commit();
 }

执行结果如下:

Hibernate: select * from fare f, route r where f.orgStn=r.oriCode and f.desStn=r.desCode

1-SHA-BJS-1-SHA-BJS
2-BJS-SHA-2-BJS-SHA
3-BJS-PEK-4-BJS-PEK
5-PEK-SHA-5-PEK-SHA
5-PEK-SHA-6-PEK-SHA
5-PEK-SHA-7-PEK-SHA
7-BBB-AAA-3-BBB-AAA
8-PEK-SHA-5-PEK-SHA
8-PEK-SHA-6-PEK-SHA
8-PEK-SHA-7-PEK-SHA
9-PEK-SHA-5-PEK-SHA
9-PEK-SHA-6-PEK-SHA
9-PEK-SHA-7-PEK-SHA
10-PEK-SHA-5-PEK-SHA
10-PEK-SHA-6-PEK-SHA
10-PEK-SHA-7-PEK-SHA

 

使用sql进行联合查询时,只查询了一次,避免了N+1的问题,通过addEntity指定了返回的类型,返回的时候对象数组的列表, 通过使用

for (Object[] obj : list) {
      FareRoute fr = new FareRoute((Fare)obj[0], (Route)obj[1]);

}

得到了想要的FareRoute对象。

 

总结:使用SQL的方式,解决了没有外键关联的多表联合查询时的N+1问题,需要自己对得到的List<Object[]>进行一些处理,但是这个处理并不麻烦,我认为可以接受,这样算是在编码繁琐性和性能之间的一个折衷。

 

希望能帮助到大家,与大家共同进步。

 

 

 

hibernate联合查询问题

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
在Session的缓存中存放的是相互关联的对象图。默认情况下,当Hibernate从数据库中加载Customer对象
Hibernate联合主键: 1.主键类UserId实现Serializable接口,重写hashCode()和equals()方法,使用@Emb
在关系型数据库中,通过连接运算符可以实现多个表联合查询。而非关系型数据库的特点是表之间属于弱
在关系型数据库中,通过连接运算符可以实现多个表联合查询。而非关系型数据库的特点是表之间属于弱
在关系型数据库中,通过连接运算符可以实现多个表联合查询。而非关系型数据库的特点是表之间属于弱
案例 一个博客系统中,用户可以任意发表博文(Post),用户还可以对博文进行评论(Comment)。于是
在关系型数据库中,通过连接运算符可以实现多个表联合查询。而非关系型数据库的特点是表之间属于弱
在关系型数据库中,通过连接运算符可以实现多个表联合查询。而非关系型数据库的特点是表之间属于弱
为了方便明显的看出效果,我们先建立一张新闻表(news),表的结构如下: 现在我要去对这批数据进行
SELECT CONCAT("ID->",cls_id,":",cls_name,":",cls_zid) AS 联合结果 FROM oc_ocms.ocms_class
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号