1 懒加载 (感觉用处不是很大)

  • 需要的时候加载,不需要的时候就不加载。

1.1 环境的搭建

  • hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <!--
        一个sessionFactory就代表一个数据库的描述
    -->
<session-factory>
    <!-- 链接数据库的用户名 -->
    <property name="connection.username">root</property>
    <!-- 链接数据库的密码 -->
    <property name="connection.password">root</property>
    <!-- 链接数据库的驱动 -->
    <property name="connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <!-- 链接数据库的url -->
    <property name="connection.url">
        jdbc:mysql://localhost:3306/hibernate
    </property>
    <!--
        方言
        告诉hibernate用什么样的数据库,将来会生成什么样的sql语句
    -->
    <property name="dialect">
        org.hibernate.dialect.MySQLDialect
    </property>
    <!--
        hibernate对表的策略
        validate  在hibernate容器启动的时候,根据映射文件和持久化类校验表
        create    每次当hibernate启动的时候,都会根据持久化类和映射文件创建表
        create-drop  每次当hibernate启动的时候,都会根据持久化类和映射文件创建表,销毁的时候删除表
        update  检查,如果和映射文件不一致,则更新表的结构,如果没有表,则会创建表
    -->
    <property name="hbm2ddl.auto">update</property>

    <!--
            显示sql语句
        -->
    <property name="show_sql">true</property>
    <property name="format_sql">true</property>
    <property name="current_session_context_class">thread</property>

    <mapping resource="com/xuweiwei/vo/Classes.hbm.xml"/>
    <mapping resource="com/xuweiwei/vo/Student.hbm.xml"/>

</session-factory>
</hibernate-configuration>
  • Classes.java
package com.xuweiwei.vo;

import java.io.Serializable;
import java.util.Set;

/**
 * 班级
 */
public class Classes implements Serializable{
    private Long cid;
    private String name;
    private String description;

    private Set<Student> students ;

    public Long getCid() {
        return cid;
    }

    public void setCid(Long cid) {
        this.cid = cid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Classes{" +
                "cid=" + cid +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                ", students=" + students +
                '}';
    }
}
  • Classes.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.xuweiwei.vo.Classes" >

        <id name="cid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>

        <set name="students" cascade="save-update" inverse="false">
            <key>
                <column name="cid"/>
            </key>
            <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
  • Student.java
package com.xuweiwei.vo;

import java.io.Serializable;

/**
 * 学生
 */
public class Student implements Serializable{
    private Long sid;
    private String name;
    private String description;

    private Classes classes;

    public Long getSid() {
        return sid;
    }

    public void setSid(Long sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Classes getClasses() {
        return classes;
    }

    public void setClasses(Classes classes) {
        this.classes = classes;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", name='" + name + '\'' +
                ", description='" + description + '\'' +
                '}';
    }
}
  • Student..hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.xuweiwei.vo.Student">
        <id name="sid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>
        <many-to-one name="classes" column="cid" class="com.xuweiwei.vo.Classes"/>

    </class>
</hibernate-mapping>

1.2 类的延迟加载

  • 示例:使用load方法
    @Test
    public void testLoad(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        Classes classes1 =  (Classes) session.load(Classes.class,1L);
        System.out.println(classes1);
        session.close();
    }
  • 示例:在映射文件上的class元素上配置lazy属性
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.xuweiwei.vo.Classes" lazy="false" >

        <id name="cid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>

        <set name="students" cascade="save-update" inverse="false">
            <key>
                <column name="cid"/>
            </key>
            <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

1.3 集合的延迟加载

1.3.1 lazy="true"

  • 默认情况下,集合就是延迟加载。
  • 只有当遍历集合中的元素的时候,才发出查询SQL
 @Test
    public void testCollectionLazy(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        Classes classes =  (Classes) session.get(Classes.class,1L);
        Set<Student> students =  classes.getStudents();
        for(Student s : students){
            System.out.println(s);
        }

        session.close();
    }

1.3.2 lazy="false"

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.xuweiwei.vo.Classes" >

        <id name="cid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>

        <set name="students" cascade="save-update" inverse="false" lazy="false" >
            <key>
                <column name="cid"/>
            </key>
            <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
    @Test
    public void testCollectionLazy(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        Classes classes =  (Classes) session.get(Classes.class,1L);
        Set<Student> students =  classes.getStudents();
        for(Student s : students){
            System.out.println(s);
        }

        session.close();
    }
  • 当查询班级的同时查询班级下的所有学生信息。

1.3.3 lazy="extra" 更进一步

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.xuweiwei.vo.Classes" >

        <id name="cid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>

        <set name="students" cascade="save-update" inverse="false" lazy="extra" >
            <key>
                <column name="cid"/>
            </key>
            <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
    @Test
    public void testCollectionLazy(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        Classes classes =  (Classes) session.get(Classes.class,1L);
        System.out.println(classes.getStudents().size());

        session.close();
    }
  • 查询的SQL如下:

1.4 延迟加载的总结

  • 延迟加载(懒加载)就是通过控制发出SQL的时间来提升效率的。

2 抓取策略fetch

  • fetch="select",默认
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.xuweiwei.vo.Classes" >

        <id name="cid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>

        <set name="students" cascade="save-update" inverse="false" fetch="select" >
            <key>
                <column name="cid"/>
            </key>
            <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
  • 示例:查询所有的班级以及班级下面的所有学生(会引起N+1问题)
  @Test
    public void testCollection(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        Classes classes1 =  (Classes) session.load(Classes.class,1L);
        session.close();
        System.out.println(classes1.getName());

    }
    • 所谓的N+1问题:

      • 1:就是Hibernate在查询所有的班级的信息,直接通过select * from classes
      • N:就是Hibernate通过外键,到student表中查询,比如classes表中有4条数据,那么Hibernate会这样发出SQL语句:select * from student where cid = 1;select * from student where cid =2;……  
  • 其实:在查询所有班级的信息的同时查询班级下面的所有学生的信息,一般我们写SQL会这样写
SELECT  s.*
FROM student s WHERE s.`cid` 、IN (SELECT cid FROM classes);
  • 这是个子查询。所以fetch应该是"subselect"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.xuweiwei.vo.Classes" >

        <id name="cid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>

        <set name="students" cascade="save-update" inverse="false" fetch="subselect" >
            <key>
                <column name="cid"/>
            </key>
            <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
 /**
     * 查询所有的班级以及班级下面的所有学生
     */
    @Test
    public void testClassesAndStudent(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        //查询所有的班级以及所有的学生
        List<Classes> classesList = session.createQuery("from Classes").list();
        System.out.println(classesList);

        for(Classes classes : classesList){
            Set<Student> students = classes.getStudents();
            for(Student student : students){
                System.out.println(student);
            }
        }

        session.close();

    }
  • 所以,如果是子查询,fetch="subselect"效率高点。
  • 示例:如果我们需要查询班级为1号的信息和1号班级下的所有学生的信息,那么我们一般是这些写SQL的
SELECT c.*,s.*
FROM classes c
LEFT OUTER JOIN student s
ON c.cid = s.cid
  • 所以,这个时候,fetch要设置为join
<?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Classes" >

    <id name="cid">
        <generator class="increment"/>
    </id>
    <property name="name"/>
    <property name="description"/>

    <set name="students" cascade="save-update" inverse="false" fetch="join" >
        <key>
            <column name="cid"/>
        </key>
        <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
    </set>
</class>
</hibernate-mapping>
   @Test
    public void testOneClassesAndStudents(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        Classes Classes = (Classes) session.get(Classes.class,1L);
        Set<Student> students = Classes.getStudents();
        for(Student student : students){
            System.out.println(student);
        }

        session.close();

    }

3 lazy和fetch

  • 当fetch为join,我们知道Hibernate是直接发出SQL查询的,所以lazy不会起作用的。
  • 当fetch为select,先加载classes后加载student,而lazy决定什么时候加载student。

4 HQL(Hibernate Query Language)

4.1 单表的HQL

  • 示例:查询所有班级的信息
    /**
     * 查询所有的班级
     */
    @Test
    public void testQueryClasses(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Classes> classesList = session.createQuery("from Classes").list() ;

        session.close();

    }
  • 示例:查询班级的名称和描述信息
 /**
     * 查询所有班级的名称和描述信息
     */
    @Test
    public void testQueryClassesNameAndDescription(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Object[]> list = session.createQuery("select name,description from Classes").list() ;

        session.close();

    }
  • 示例:根据cid查询班级信息
  /**
     * 根据cid查询班级信息
     */
    @Test
    public void testQueryClassesByCid(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Classes> classesList = session.createQuery("from Classes where cid = ?").setParameter(0,1L).list();
        for(Classes c:classesList){
            System.out.println(c);
        }

        session.close();
    }
  • 示例:根据cid查询班级的信息
 /**
     * 根据cid查询班级信息
     */
    @Test
    public void testQueryClassesByCid(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Classes> classesList = session.createQuery("from Classes where cid =:cid ").setParameter("cid",1L).list();

        for(Classes c:classesList){
            System.out.println(c);
        }

        session.close();
    }
  • 示例:查询班级的个数
  /**
     * 查询班级的个数
     */
    @Test
    public void testCount(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        Object object = session.createQuery("select count(*) from Classes").uniqueResult();
        System.out.println(object);

        session.close();
    }
  • 示例:查询主键的最大值
/**
     * 查询cid的最大值
     */
    @Test
    public void testSelectMaxCid(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        Long max = (Long) session.createQuery("select max(cid) from Classes").uniqueResult();
        System.out.println(max);

        session.close();

    }

4.2 多表的HQL

  • 内连接
 /**
     * 内连接
     */
    @Test
    public void testEq(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Object[]> list = session.createQuery("from Classes c ,Student s where c.cid = s.classes.cid").list();

        session.close();

    }
  • 示例:内连接
    @Test
    public void testInnerJoin(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Object[]> list = session.createQuery("from Classes c inner join c.students s").list();

        session.close();
    }
  • 示例:左外连接
@Test
    public void testLeftOuterJoin(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Object[]> list = session.createQuery("from Classes c left outer join c.students s").list();

        session.close();

    }
  • 示例:迫切左外连接
    @Test
    public void testLleftOuterJoinFetch(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Classes> list = session.createQuery("from Classes c left outer join fetch c.students s").list();

        session.close();
    }
  • 示例:迫切内连接
    @Test
    public void testInnerJoinFetch(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();

        List<Classes> list = session.createQuery("from Classes c inner join fetch c.students s").list();

        session.close();
    }

Hibernate (四)的更多相关文章

  1. hibernate(四) 双向多对多映射关系

    序言 莫名长了几颗痘,真TM疼,可能是现在运动太少了,天天对着电脑,决定了,今天下午花两小时去跑步了, 现在继上一章节的一对多的映射关系讲解后,今天来讲讲多对多的映射关系把,明白了一对多,多对多个人感 ...

  2. Hibernate(四)之对象状态及一级缓存

    一.Hibernate中的对象状态 1.1.瞬时态(临时态) 没有与Hibernate产生关联 与数据库中的记录没有产生关联(有关联就是与数据库中表的id相对应) 获得:一般都只直接创建(new) 瞬 ...

  3. Hibernate(四)结构-基础语义和事务

    一.基础语义 核心: Configuration SessionFactory Session 二.Configuration Configuration类负责管理Hibernate的配置信息,Hib ...

  4. hibernate(四)__由表逆向创建Domain对象和对象关系映射文件

    之前我们是手写Domain对象和对象关系映射文件->然后生成数据库中的Table. 现在我们反过来先在数据库中建好Table->然后用工具生成Domain对象和对象关系映射文件. 步骤: ...

  5. Hibernate四 批量处理

    Hibernate批量处理一 批量插入将很多条记录插入数据库时,Hibernate通常会采用以下做法:public void test() { for(int i=0;i<1000;i++){ ...

  6. Hibernate(四)——缓存策略+lazy

    Hibernate作为和数据库数据打交道的框架,自然会设计到操作数据的效率问题,而对于一些频繁操作的数据,缓存策略就是提高其性能一种重要手段,而Hibernate框架是支持缓存的,而且支持一级和二级两 ...

  7. ORM框架Hibernate (四) 一对一单向、双向关联映射

    简介 在上一篇博客说了一下多对一映射,这里再说一下一对一关联映射,这种例子在生活中很常见,比如一个人的信息和他的身份证是一对一.又如一夫一妻制等等. 记得在Java编程思想上第一句话是“一切皆对象”, ...

  8. ssh架构之hibernate(四)二级缓存

    二级缓存使用步骤: 1.拷贝jar包 2.配置Hibernate.cfg.xml文件 a.#开启二级缓存 hibernate.cache.use_second_level_cache=true b.# ...

  9. Hibernate(四)

    ==================================投影(查询)=============================投影查询:查询一个持久化类的一个或多个属性值    1.将每条 ...

  10. Hibernate(四)--延迟加载(lazyload)

    hibernate中的延迟加载(lazyload)分属性的延迟加载和关系的延迟加载 属性的延迟加载: 当使用load的方式来获取对象的时候,只有访问了这个对象的属性,hibernate才会到数据库中进 ...

随机推荐

  1. Coursera课程 Programming Languages, Part C 总结

    碎言碎语 和前面的 ML 和 Racket 感觉明显不一样了,一边学着一边觉得这真是一门奇怪的语言,有着各种奇怪的语法,不过真的算是一个奇妙的体验(相比前面的两门语言,Ruby 的学习资源多了不少). ...

  2. Android 屏幕刷新机制

    这次就来梳理一下 Android 的屏幕刷新机制,把我这段时间因为研究动画而梳理出来的一些关于屏幕刷新方面的知识点分享出来,能力有限,有错的地方还望指点一下.另外,内容有点多,毕竟要讲清楚不容易,所以 ...

  3. Linux(常用命令) 中常用的压缩丶解压缩格式命令和参数详解

    Linux中常用的压缩格式后缀名有:①.zip  ②.gz  ③.bz2  ④.tar.gz  ⑤.tar.bz2 ①.zip后缀名格式 1.压缩 语法: ①zip 压缩文件名 源文件 (压缩文件) ...

  4. [bzoj1594] [Usaco2008 Jan]猜数游戏

    二分答案(二分没冲突的前Q-1个问题),用并查集判定(用法同bzoj 1576) 假设一个询问区间[l,r],最小干草堆数目是A,我们可以得出[l,r]上的干草堆数目都>=A. 二分出mid后, ...

  5. 史上最全最强Charles截取手机https协议数据包教程(附上利用此技术制作最近微信比较火的头脑王者辅助外挂)!

    纯原创,思路也是本人花了半个小时整理出来的,整个完成花费了本人半天时间,由于不才刚大学毕业,所以有的编码方面可能不入大牛们的眼,敬请原谅!如有转载请附上本地址,谢谢! 最近微信朋友圈刚刚被跳一跳血洗, ...

  6. 安装myeclipse后,打开时弹出:“该站点安全证书的吊销证书不可用”,怎样解决?

    1.当弹出"该站点安全证书的吊销信息不可用.是否继续?"的对话框时,点击"查看证书",切换到"详细信息"TAB页,找到其"CRL分 ...

  7. Jfinal——实践出真知

    什么是Jfinal? JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速.代码量少.学习简单.功能强大.轻量级.易扩展.Restful.在拥有Java语言所 ...

  8. Logback日志配置的简单使用

    Logback介绍 Logback是由log4j创始人设计的又一个开源日志组件.logback当前分成三个模块:logback-core,logback- classic和logback-access ...

  9. phpstorm ctrl+shift+F键不管用,不弹出搜索弹框

    般热键冲突搜狗默认简繁切换组合键位ctrl+shift+F故outlook2011按三建且失效应该能看搜狗输入状态简繁变搜狗设置按键-取消选简繁切换热键即在任务栏的语言地方点击一下再点击语言首选项.进 ...

  10. Xshell学习--菜鸟篇

    http://www.cnblogs.com/perseverancevictory/p/4910145.html 1)关于Xshell 网上更多的资料里提到的SSH客户端是putty,因为简单.开源 ...