前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SSH框架之旅-hibernate(4)

SSH框架之旅-hibernate(4)

作者头像
Wizey
发布2018-08-30 09:40:29
1.6K0
发布2018-08-30 09:40:29
举报
文章被收录于专栏:编程心路编程心路

hibernate

1.hibernate 查询方式


    1. 对象导航查询 一个对象关联了另一个对象,并且两者是一对多的关系,那么通过一个(一方)对象就可以找到另外一个(多方)对象。例如:由一个班级就可以找到班上所有的学生,这种通过班级对象找到学生对象的查询方式就叫做对象导航查询。
    1. OID 查询 又称对象唯一标识符查询。根据对象属性中的唯一标识值来查询这个对象,session 的 get() 方法还有下面说到的 load() 方法,都是 OID 的查询方式。
    1. HQL 查询 使用 Query 对象调用相关的方法来做查询,需要写相关的hql语句,这是 hibernate 提供的查询语言,hql 语句中写的是实体类和属性,而 sql 语句中写的是数据表和字段。
    1. QBC 查询 使用 Criteria 对象调用相关的方法做查询,但是不需要写语句,调用的是方法,操作的也是实体类和属性。
    1. SQL 查询 使用 SQLQuery 对象写普通的 sql 语句来做查询,但由于数据库的不同,sql 语句也有所不同,所以一般不使用这种查询方式。但如果需要底层数据库的 SQL 方言查询时,还是可以使用这种方式的。hibernate 种也封装了 SQL 查询的对象 SQLQuery。

2.基本代码


下面的例子也是基于班级和学生一对多关系说明的。

2.1 实体类代码

  • 学生实体类
代码语言:javascript
复制
package cc.wenshixin.entity;

public class Student {
    private Integer id; // 学号
    private String name; // 姓名
    private Integer age; // 年龄

    private Banji banji; // 所属班级

    public Student() {

    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    //get,set方法在此省略,必须要写的
}
  • 班级实体类
代码语言:javascript
复制
package cc.wenshixin.entity;

import java.util.HashSet;
import java.util.Set;

public class Banji {
    private Integer id; //编号
    private String name; //名称
    
    private Set<Student> setStudent = new HashSet<Student>(); //班级里的学生

    public Banji() {

    }

    public Banji(String name) {
        this.name = name;
    }
    //get,set方法在此省略,必须要写的
}
  • 工具类
代码语言:javascript
复制
package cc.wenshixin.utility;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtility {
    private static Configuration cfg = null;
    private static SessionFactory sessionFactory = null;

    static{
        cfg = new Configuration().configure();
        sessionFactory = cfg.buildSessionFactory();
    }
    
    //获得sessionFactory对象的方法
    public static SessionFactory getSessionFactory()
    {
        return sessionFactory;
    }   
}

2.2 映射文件

  • 学生实体类映射文件
代码语言:javascript
复制
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cc.wenshixin.entity.Student" table="student">
        <id name="id" type="java.lang.Integer" column="sid">
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String" column="sname">
        </property>
        <property name="age" type="java.lang.Integer" column="age">
        </property>
        <many-to-one name="banji" class="cc.wenshixin.entity.Banji" column="sbid">
        </many-to-one>
    </class>
</hibernate-mapping>
  • 班级实体类映射文件
代码语言:javascript
复制
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cc.wenshixin.entity.Banji" table="banji">
        <id name="id" type="java.lang.Integer" column="bid">
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String" column="bname">
        </property>
        <set name="setStudent" table="student" cascade="save-update">
            <key column="sbid">
            </key>
            <one-to-many class="cc.wenshixin.entity.Student" />
        </set>
    </class>
</hibernate-mapping>
  • 核心配置文件
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
      <!-- 数据库信息配置 -->
      <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
      <property name="connection.url">jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=UTF-8</property>
      <property name="connection.username">用户名</property>
      <property name="connection.password">密码</property>
      
      <!-- hibernate功能选择 -->
      <property name="show_sql">true</property>
      <property name="format_sql">true</property>
      <property name="hbm2ddl.auto">update</property>
      <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
      
      <!-- 加载映射文件 -->
      <mapping resource="cc/wenshixin/entity/Student.hbm.xml"/>
      <mapping resource="cc/wenshixin/entity/Banji.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

2.3 数据初始化

代码语言:javascript
复制
    @Test
    //初始化数据
    public void initData()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //插入数据
            Banji banji1 = new Banji("计科一班");
            Banji banji2 = new Banji("计科二班");
            Banji banji3 = new Banji("计科三班");
            Banji banji4 = new Banji("计科四班");
            
            Student student1 = new Student("小明", 20);
            Student student2 = new Student("小红", 19);
            Student student3 = new Student("小智", 21);
            Student student4 = new Student("小张", 20);
            Student student5 = new Student("小李", 19);
            Student student6 = new Student("老王", 23);
            Student student7 = new Student("小魏", 20);
            
            banji1.getSetStudent().add(student1);
            banji1.getSetStudent().add(student3);
            banji2.getSetStudent().add(student2);
            banji2.getSetStudent().add(student5);
            banji2.getSetStudent().add(student4);
            banji3.getSetStudent().add(student6);
            banji4.getSetStudent().add(student7);
            
            session.save(banji1);
            session.save(banji2);
            session.save(banji3);
            session.save(banji4);
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

2.4 对象导航查询测试

代码语言:javascript
复制
    @Test
    //对象导航查询方式
    public void test()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Banji banji = session.get(Banji.class, 2);
            Set<Student> setStudent = banji.getSetStudent();

            System.out.println(setStudent.size());
            for (Student student : setStudent) {
    System.out.println(student.getId()+":"+student.getName()+":"+student.getAge());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

3.HQL 查询


常用的 hql 语句(关键字大小写都可以的):

    1. 查询所有: from 实体类名称
    1. 条件查询(使用 AS 关键词设置别名): from 实体类名称 as 别名 where 别名.属性名称=? from 实体类名称 as 别名 where 别名.属性名称=? and 别名.属性名称=? from 实体类名称 as 别名 where 别名.属性名称 like ?
    1. 排序查询: from 实体类名称 as 别名 order by 别名.属性名称 asc/desc
    1. 分页查询: 通过调用方法来实现,设置开始位置 query.setFirstResult(0);,设置每页记录数 query.setMaxResults(3);
  • 5.投影查询: 在投影查询中才会用到 SELECT 关键字,在前面的查询中是用不到的,并且不能使用 * 号。 select 属性名称 from 实体类名称
  • 6.函数查询: 在HQL中也是可以使用 sql 函数的,count()函数计算数量,sum()函数求和,avg()函数计算平均值,max()函数计算最大值,min()函数计算最小值。

hql语句查询步骤:

    1. 创建 Query 对象,写 hql 语句
    1. 调用 query 对象里面的方法得到结果

3.1 查询所有

代码语言:javascript
复制
    @Test
    //HQL查询表中所有数据
    public void testQueryAll()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Banji> query = session.createQuery("FROM Banji");
            
            List<Banji> list = query.list();
            
            for(Banji banji:list)
            {
                System.out.println(banji.getId()+":"+banji.getName());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

3.2 条件查询

代码语言:javascript
复制
    @Test
    //HQL带条件的查询
    public void testQueryWhere1()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Banji> query = session.createQuery("FROM Banji AS banji WHERE banji.id=?");
            query.setParameter(0, 2);
            
            List<Banji> list = query.list();
            
            for(Banji banji:list)
            {
                System.out.println(banji.getId()+":"+banji.getName());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

    @Test
    //模糊条件查询
    public void testQueryWhere2()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Banji> query = session.createQuery("FROM Banji AS banji WHERE banji.name LIKE ?");
            query.setParameter(0, "%计科%");
            
            List<Banji> list = query.list();
            
            for(Banji banji:list)
            {
                System.out.println(banji.getId()+":"+banji.getName());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

3.3 排序查询

代码语言:javascript
复制
    @Test
    //排序查询
    public void testQueryOrder()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Banji> query = session.createQuery("FROM Banji AS banji ORDER BY banji.id DESC");
            
            List<Banji> list = query.list();
            
            for(Banji banji:list)
            {
                System.out.println(banji.getId()+":"+banji.getName());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

3.4 分页查询

代码语言:javascript
复制
    @Test
    //分页查询
    public void testQueryPage()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Student> query = session.createQuery("FROM Student");
            
            query.setFirstResult(2);
            query.setMaxResults(3);
            
            List<Student> list = query.list();
            
            for(Student student : list)
            {
                System.out.println(student.getId()+":"+student.getName()+":"+student.getAge());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

3.5 投影查询

听起来很高大上,其实就是查询数据表中的某一列。。。

代码语言:javascript
复制
@Test
    //投影查询
    public void testQueryShade()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //注意返回的结果是一个object类型,而不是一个实体类的类型
            Query<Object> query = session.createQuery("SELECT name FROM Student");
            
            List<Object> list = query.list();
            
            for(Object object : list)
            {
                System.out.println(object);
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

3.6 函数查询

需要类型转换

代码语言:javascript
复制
    @Test
    //函数查询
    public void testQueryFunction()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Object> query = session.createQuery("SELECT COUNT(id) FROM Student");
            
            Object object = query.uniqueResult(); //获取查询结果唯一值
            
            //先转换为long类型,再转换成int类型
            Long obj = (Long)object;
            int count = obj.intValue();
            System.out.println(count);
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

4.QBC 查询


QBC 查询是通过 Restrictions 类的静态方法来实现的,具体的方法如下表所示。

静态方法

说明

Restrictions.eq()

等于

Restrictions.allEq()

使用 Map,使用 key/value 进行多个等于的比较

Restrictions.gt()

大于 >

Restrictions.ge()

大于等于 >=

Restrictions.lt()

小于 <

Restrictions.le()

小于等于 <=

Restrictions.between()

对应 sql 语句中的 between 语句

Restrictions.like()

对应 sql 的like 语句

Restrictions.in()

对应 sql 的 in 语句

Restrictions.and()

and 关系

Restrictions.or()

or 关系

Restrictions.sqlRestriction()

sql 限定查询

4.1 查询所有

代码语言:javascript
复制
    @Test
    public void testAll()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;      
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //查询所有
            Criteria criteria = session.createCriteria(Student.class);
            List<Student> list = criteria.list();
            
            for (Student student : list) {
                System.out.println(student.getId()+":"+student.getName()+":"+student.getAge());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

4.2 条件查询

代码语言:javascript
复制
    @Test
    public void testWhere1()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;      
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //条件查询
            Criteria criteria = session.createCriteria(Student.class);
            criteria.add(Restrictions.eq("id", 4)); //相当于where sid = 4
            criteria.add(Restrictions.eq("age", 19)); 
            List<Student> list = criteria.list();
            
            for (Student student : list) {
                System.out.println(student.getId()+":"+student.getName()+":"+student.getAge());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

    @Test
    public void testWhere2()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;      
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //模糊查询
            Criteria criteria = session.createCriteria(Student.class);
            criteria.add(Restrictions.like("name", "%小%"));
            List<Student> list = criteria.list();
            
            for (Student student : list) {
                System.out.println(student.getId()+":"+student.getName()+":"+student.getAge());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

4.3 排序查询

代码语言:javascript
复制
    @Test
    public void testOrder()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;      
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //排序查询
            Criteria criteria = session.createCriteria(Student.class);
            criteria.addOrder(Order.desc("id"));
            List<Student> list = criteria.list();
            
            for (Student student : list) {
                System.out.println(student.getId()+":"+student.getName()+":"+student.getAge());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

4.4 分页查询

话不多说,请看代码。

代码语言:javascript
复制
    @Test
    public void testPage()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;      
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //分页查询
            Criteria criteria = session.createCriteria(Student.class);
            criteria.setFirstResult(1);
            criteria.setMaxResults(4);
            List<Student> list = criteria.list();
            
            for (Student student : list) {
                System.out.println(student.getId()+":"+student.getName()+":"+student.getAge());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

4.5 函数查询

同 HQL 一样,QBC 也有函数查询,通过 Projections 类中的静态方法实现。

代码语言:javascript
复制
    @Test
    public void testFunction()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;      
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //函数查询
            Criteria criteria = session.createCriteria(Student.class);
            criteria.setProjection(Projections.rowCount());
            List<Student> list = criteria.list();
            
            Object obj = criteria.uniqueResult();
            Long lobj = (Long)obj;
            int count = lobj.intValue();
            
            System.out.println(count);
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

4.6 离线查询

DetachedCriteria 翻译为离线条件查询,他不不依赖 Session 来创建,所以 DetachedCriteria 可以被其他层使用条件封装,在交给 DAO 层查询,在 SSH 框架的整合上经常使用。

代码语言:javascript
复制
    @Test
    public void testOutLine()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;      
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            //离线查询
            DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Student.class);
            Criteria criteria = detachedCriteria.getExecutableCriteria(session);
            List<Student> list = criteria.list();
            
            for (Student student : list) {
                System.out.println(student.getId()+":"+student.getName()+":"+student.getAge());
            }
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

5.hibernate 检索策略


5.1 多表连接查询。

在做表的查询时,有时要采用连接查询进行对表联合查询,下面是 mysql 中的多表查询写法。

  • 交叉查询 查询的结果是返回被连接的表中的所有数据行的笛卡尔积,返回的结果条数也就是一个表的数据记录乘以另一个比表的数据记录数,在开发中最好不要使用交叉查询,因为数据量不算很大时,查询效率就极低,在设计数据表时应该避免这种查询方式。 select * from student, banji;
  • 内连接 select * from student, banji where student.sid=banji.bid; select * from student inner join banji on student.sid=banji.bid;
  • 外连接
    • 左外连接 select * from student left outer join banji on student.sid=banji.bid;
    • 右外连接 select * from student right outer join banji on student.sid=banji.bid;

5.2 HQL 连接查询

5.2.1 内连接查询

内连接有一般的内连接查询,还有迫切内连接查询,迫切连接查询比一般的内连接查询多了一个 fetch 关键字两种方式返回的结果集不同。

代码语言:javascript
复制
    @Test
    //内连接查询
    public void testQueryInner()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Object> query = session.createQuery("from Banji as b inner join b.setStudent");
            
            List<Object> list = query.list(); //返回的是一个二维对象数组,list的每部分包含两个表中的数据
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

    @Test
    //迫切内连接查询
    public void testQueryInnerFecth()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Object> query = session.createQuery("from Banji as b inner join fetch b.setStudent");
            
            List<Object> list = query.list(); //返回的是一个一维对象数组,只包含联合表student中的数据
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }
5.2.2 外连接

外连接也分一般的外连接查询和迫切外连接查询,并且还有左外连接和右外连接之分。

代码语言:javascript
复制
    @Test
    //迫切外连接查询
    public void testQueryOuterFecth()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Object> query = session.createQuery("from Banji as b left outer join fetch b.setStudent");
            
            List<Object> list = query.list(); //返回的是一个一维对象数组,只包含联合表student中的数据
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }
    
    @Test
    //外连接查询
    public void testQueryOuter()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Query<Object> query = session.createQuery("from Banji as b left outer join b.setStudent");
            
            List<Object> list = query.list(); //返回的是一个二维对象数组,包含两个表中的数据
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

5.3 HQL 检索(抓取)策略

hibernate 的检索策略也是提升性能的一种方式,可以在获取关联对象的时候,对发送的语句进行优化,但是抓取策略需要和延迟加载一起使用来提升性能。

在前面,使用的是 session 对象的 get() 方法来发送语句查询数据库,但还可以 load() 来做查询,两者的区别是:get() 方法会马上发送语句查询数据库,而 load() 方法只有在执行到使用查询对象语句时才会发送语句查询数据库,load的延迟方式就是延迟查询方式。

延迟查询分为两类:

    1. 类级别延迟:根据 id 查询返回实体类对象,调用 load 方法不会马上发送语句。
    1. 关联级别延迟:查询一个班级,再查询一个班级的所有学生是否需要延迟,这个过程就称为关联级别延迟。

延迟就是发送 sql 语句的时间是否是随写随发的,还是用到的数据值的时候再发。

关于类级别延迟就是方法的区别,而关联级别延迟需要在映射文件中进行配置,根据班级来得到所有学生,就需要在班级实体类的映射文件中配置。在 set 标签上使用fetch属性和 lazy 属性。fetch 的默认就是 select 值,如果 fetch 属性的值为 join 那么 lazy 里面的值设置就失效了。设置 lazy 的值:true:表示延迟(默认);false:表示不延迟;extra表示极其延迟。

下面是示例代码:

类级别延迟

代码语言:javascript
复制
    @Test
    //get查询方式
    public void testGet()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Banji banji = session.get(Banji.class, 2);
            //这一句就发送sql语句
            Set<Student> setStudent = banji.getSetStudent();
            
            //这一句要打印的值只有在事务提交成功后才会显示
            System.out.println(setStudent.size()); 
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

    @Test
    //load查询方式
    public void testLoad()
    {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try{
            sessionFactory = HibernateUtility.getSessionFactory();
            session = sessionFactory.openSession();
            tx = session.beginTransaction();
            
            Banji banji = session.load(Banji.class, 2);
            //这一句没有发送sql语句
            Set<Student> setStudent = banji.getSetStudent();

            //这一句才发送了sql语句,在事务提交后显示需要打印的值
            System.out.println(setStudent.size());
            
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        }finally {
            session.close();
            sessionFactory.close();
        }
    }

关联级别延迟

在班级实体类的配置文件中增加如下配置:

代码语言:javascript
复制
<set name="setStudent" table="student" cascade="save-update" lazy="false">
    <key column="sbid">
    </key>
    <one-to-many class="cc.wenshixin.entity.Student" />
</set>

批量抓取配置

为了进一步的提高查询的效率,hibernate 还有批量抓取的配置,只需要在set文件中加上 batch-size 的属性,在里面写上数字,数字越大,查询时发送的语句就越少,最大一般写 10。

代码语言:javascript
复制
<set name="setStudent" table="student" cascade="save-update" lazy="false"  batch-size="10">
    <key column="sbid">
    </key>
    <one-to-many class="cc.wenshixin.entity.Student" />
</set>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.09.27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.hibernate 查询方式
  • 2.基本代码
    • 2.1 实体类代码
      • 2.2 映射文件
        • 2.3 数据初始化
          • 2.4 对象导航查询测试
          • 3.HQL 查询
            • 3.1 查询所有
              • 3.2 条件查询
                • 3.3 排序查询
                  • 3.4 分页查询
                    • 3.5 投影查询
                      • 3.6 函数查询
                      • 4.QBC 查询
                        • 4.1 查询所有
                          • 4.2 条件查询
                            • 4.3 排序查询
                              • 4.4 分页查询
                                • 4.5 函数查询
                                  • 4.6 离线查询
                                  • 5.hibernate 检索策略
                                    • 5.1 多表连接查询。
                                      • 5.2 HQL 连接查询
                                        • 5.2.1 内连接查询
                                        • 5.2.2 外连接
                                      • 5.3 HQL 检索(抓取)策略
                                      领券
                                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档