`
sxj19881213
  • 浏览: 8646 次
社区版块
存档分类
最新评论

hibernate联合查询问题

阅读更多

最近在用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[]>进行一些处理,但是这个处理并不麻烦,我认为可以接受,这样算是在编码繁琐性和性能之间的一个折衷。

 

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

 

 

 

0
1
分享到:
评论

相关推荐

    hibernate关联查询 实例源码

    hibernate关联查询 实例源码 java web 如果不明白hibernate关联查询不明白的可以看看,保证马上学会,注释,数据库都有,很简单易学的源码,谢谢下载!

    hibernate多表联合查询

    在实际项目开发中,我们经常需要处理复杂的数据库查询,特别是涉及到多个表之间的关联查询。Hibernate作为一款流行的Java持久层框架,提供了一种非常便捷的方式来处理这些问题。本文将详细介绍如何利用Hibernate进行...

    hibernateHQL关联查询

    ### Hibernate HQL 关联查询详解 #### 一、引言 在进行数据库操作时,关联查询是必不可少的一部分,尤其在处理复杂的数据结构时更是如此。Hibernate作为一种流行的Java持久层框架,提供了强大的对象关系映射(ORM...

    Hibernate连表查询 Hibernate连表查询

    根据提供的文件信息,我们可以深入探讨Hibernate中的连表查询方法及其应用。下面将详细介绍与标题、描述及部分代码相关的...需要注意的是,在编写连表查询时要充分考虑性能问题,避免因查询复杂度过高而导致性能瓶颈。

    hibernate关联查询

    **hibernate关联查询详解** Hibernate,作为Java领域中的一款流行的ORM(对象关系映射)框架,极大地简化了数据库操作,使得开发者可以使用面向对象的方式来处理数据库事务。在实际项目中,我们经常需要处理对象...

    hibernate关联映射详解

    hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的...

    hibernate映射关系关联查询

    关于hibernate的关联操作 分享下

    Hibernate中查询语句

    Hibernate中的查询方法若HQL,详细讲解HQL与使用的具体例子

    Hibernate关联关系练习【全】

    本练习主要涵盖了Hibernate中的关联关系,这是理解Hibernate核心概念的重要一环。 首先,我们需要理解什么是关联关系。在数据库设计中,关联通常指的是表与表之间的连接,例如一对一、一对多、多对一和多对多关系。...

    hibernate实现递归查询

    本文将深入探讨如何使用Hibernate实现递归查询,以解决在数据层次结构中涉及父节点与子节点关系时的问题。递归查询通常用于处理树形结构的数据,例如组织结构、菜单系统或者文件目录等。 首先,我们需要了解递归的...

    Hibernate 多表连接分页查询示范项目

    总结,"Hibernate 多表连接分页查询示范项目"是一个实用的示例,它展示了如何在实际应用中利用 Hibernate Criteria API 实现复杂查询和分页,对于学习和掌握 Hibernate 的高级特性和数据库操作技巧非常有帮助。...

    Hibernate的MySql查询.rar

    本文将深入探讨在使用Hibernate进行MySQL查询时的一些关键知识点,以帮助开发者更好地理解和应用这些技术。 首先,我们需要理解Hibernate的核心概念。Hibernate通过提供一个中间层,将Java对象与数据库表进行映射,...

    hibernate 级联查询

    “Hibernate 级联查询”是指在使用Hibernate这个Java持久化框架时,如何处理对象之间的关联查询。Hibernate提供了级联操作来简化数据的保存、更新和删除等操作,使得开发者无需手动编写复杂的SQL语句,就能实现关联...

    Hibernate的高级查询

    当我们需要进行更复杂的数据库查询时,Hibernate提供了丰富的高级查询功能,这正是“Hibernate的高级查询”这一主题的核心所在。 在Hibernate中,高级查询主要包括HQL(Hibernate Query Language)、Criteria API和...

    hibernate子查询

    在使用Hibernate进行数据查询时,有时会遇到需要使用子查询的情况。然而,正如你所描述的,Hibernate的HQL(Hibernate Query Language)并不直接支持在`FROM`子句后跟一个子查询,这与标准的SQL语法有所差异。在HQL...

    hibernate关联映射实例

    本文将深入探讨“hibernate关联映射实例”中的关键知识点,包括一对多、多对多和继承映射,这些都是Hibernate中至关重要的概念。 1. **一对多关联映射**: 在现实世界中,一个实体可能会与多个其他实体相关联,...

    Hibernate 函数 ,子查询 和原生SQL查询

    **Hibernate函数** ...当ORM无法满足需求时,原生SQL查询则提供了一种灵活的方式,以直接操作数据库的能力来解决特定问题。理解和熟练运用这些特性,对于提升Java开发中的数据库操作效率至关重要。

    Hibernate在查询条件中创建List集合

    最后,为了防止数据的安全性问题,比如防止SQL注入,使用Hibernate的查询API可以有效避免这类风险,因为它们都是预编译的,可以自动转义特殊字符。 总结,使用Hibernate在查询条件中创建List集合是Java开发中常见的...

    hibernate联合主键全攻略

    ### Hibernate联合主键详解 #### 1. 定义联合主键 在Hibernate中定义联合主键主要依赖于`&lt;composite-id&gt;`标签。如示例文件所示,`Users`类被设计为具有联合主键,该主键由`name`和`tel`两个字段组成。在`...

    hibernate 关联表问题

    本文将深入探讨“Hibernate关联表问题”,基于给出的标题和描述,我们将重点讨论Hibernate中的多对多(Many-to-Many)关联映射。 在关系型数据库中,多对多关联是最复杂的一种关系,比如用户可以有多个角色,角色也...

Global site tag (gtag.js) - Google Analytics