Hibernate

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate 相关的知识,希望对你有一定的参考价值。

1 一对多的单向

  • 示例:一个已经存在的学生,新建一个班级,然后将该学生加入到该班级之下
    • 设置inverse="false"  
<?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="com.xuweiwei.vo.Classes">
        <id name="cid">
            <generator class="native"></generator>
        </id>
        <property name="name"/>
        <property name="description"/>

        <!--
            set元素描述了集合
              name就是属性的名称
              cascade:save-update保存或更新的时候对Student进行操作

              inverse 是否维护关系:Classes是否维护和Student之间的关系
                true 不维护关系
                false 维护关系
                default=false
        -->
        <set name="students" cascade="save-update"   >
            <!--
              key代表外键
            -->
            <key>
                <column name="cid"/>
            </key>
            <!--
                建立了对象和对象之间的关联
            -->
            <one-to-many class="com.xuweiwei.vo.Student"/>
        </set>
    </class>


</hibernate-mapping>
    • 测试代码:     
     /**
     * 已经存在一个学生,新建一个班级,把该学生加入到该班级
     */
    @Test
    public void testSaveClasses_Build(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Student student = (Student) session.get(Student.class,1L);

        Classes c = new Classes();
        c.setName("Linux");
        c.setDescription("Linux厉害");
        c.getStudents().add(student);

        session.save(c);


        tx.commit();
    }

 

  • 示例:已经存在一个学生,已经存在一个班级,将该学生加入到该班级
    /**
     * 已经存在一个学生,已经存在一个班级,将该学生加入到该班级
     *  将sid为2的学生,加入到cid=1的班级
     */
    @Test
    public void testExistStudentAndClassesBuildRealationship(){

        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Student student = (Student) session.get(Student.class,2L);
        Classes classes = (Classes) session.get(Classes.class,1L);

        classes.getStudents().add(student);


        tx.commit();


    }

 

  • 示例:将一个学生(存在)从一个班级(存在)转移到另一个班级(存在)
    /**
     * 将一个学生从一个班级转移到另一个班级
     */
    @Test
    public void testTransferClasses(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Student student1 = (Student) session.get(Student.class,1L);

        Classes classes1 = (Classes) session.get(Classes.class,1L);
        Classes classes2 = (Classes) session.get(Classes.class,2L);

        classes1.getStudents().remove(student1);

        classes2.getStudents().add(student1);

        tx.commit();
    }
    /**
     * 将一个学生从一个班级转移到另一个班级
     */
    @Test
    public void testTransferClasses(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Student student1 = (Student) session.get(Student.class,1L);

        Classes classes2 = (Classes) session.get(Classes.class,2L);

        classes2.getStudents().add(student1);

        tx.commit();
    }

 

  • 示例:解除一个班级和所有的学生之间的关系
   /**
     * 解除一个班级和所有学生之间的关系
     */
    @Test
    public void testClassesRemoveAll(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Classes classes = (Classes) session.get(Classes.class,1L);

        classes.setStudents(null);



        tx.commit();


    }

 

  • 示例:解除一个班级和其下所有学生的关系,然后建立这个班级和其它学生的关系
    /**
     * 解除一个班级的和所有学生的关系,重新建立班级和其它学生的关系
     *
     */
    @Test
    public void testRebuild(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Classes classes = (Classes) session.get(Classes.class,1L);

        List<Student> studentList = (List<Student>) session.createSQLQuery("select * from student where cid != 1 ").addEntity(Student.class).list();

        classes.setStudents(new HashSet<>(studentList));


        tx.commit();


    }

 

  • 示例:先设置学生的外键为null,然后删除指定的班级信息
    /**
     * 将cid为1的班级
     */
    @Test
    public void testCascadeDelete(){

        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Classes classes = (Classes) session.get(Classes.class,1L);

        session.delete(classes);


        tx.commit();

    }

 

  • 示例:删除班级和其下的所有学生
     <!--
            set元素描述了集合
              name就是属性的名称
              cascade:save-update保存或更新的时候对Student进行操作

              inverse 是否维护关系:Classes是否维护和Student之间的关系
                true 不维护关系
                false 维护关系
                default=false
        -->
        <set name="students" cascade="all-delete-orphan"   >
            <!--
              key代表外键
            -->
            <key>
                <column name="cid"/>
            </key>
            <!--
                建立了对象和对象之间的关联
            -->
            <one-to-many class="com.xuweiwei.vo.Student"/>
        </set>
    /**
     * 删除班级和其下的所有学生
     */
    @Test
    public void testCascadeDeleteAll(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Classes classes = (Classes) session.get(Classes.class,2L);

        session.delete(classes);


        tx.commit();
    }

 

2 一对多的双向

  • Student.java
package com.xuweiwei.vo;

import java.io.Serializable;

/**
 * 学生
 */
public class Student implements Serializable{
    private Long sid;//学生的ib
    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;
    }
}
  • Student.hbm.xml
<?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="com.xuweiwei.vo.Student">
        <id name="sid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>

        <!--
            column表示外键
        -->
        <many-to-one name="classes" class="com.xuweiwei.vo.Classes" column="cid" cascade="save-update"/>

    </class>


</hibernate-mapping>
  • Classes.hbm.xml
<?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="com.xuweiwei.vo.Classes">
        <id name="cid">
            <generator class="increment"></generator>
        </id>
        <property name="name"/>
        <property name="description"/>

        <!--
            set元素描述了集合
              name就是属性的名称
              cascade:save-update保存或更新的时候对Student进行操作

              inverse 是否维护关系:Classes是否维护和Student之间的关系
                true 不维护关系
                false 维护关系
                default=false
        -->
        <set name="students" cascade="all-delete-orphan"   >
            <!--
              key代表外键
            -->
            <key>
                <column name="cid"/>
            </key>
            <!--
                建立了对象和对象之间的关联
            -->
            <one-to-many class="com.xuweiwei.vo.Student"/>
        </set>
    </class>


</hibernate-mapping>

 

3 多对多操作 

  • 以学生和课程为例

 

3.1 配置hibernate多对多的环境

  • 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/Student.hbm.xml"/> 
    <mapping resource="com/xuweiwei/vo/Course.hbm.xml"/> 
    
    
</session-factory>
</hibernate-configuration>
  • Student.java  
package com.xuweiwei.vo;

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

public class Student implements Serializable {
    private Long sid;
    private String name;
    private String description;

    private Set<Course> courses;

    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 Set<Course> getCourses() {
        return courses;
    }

    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }
}
  • 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" length="5">
            <generator class="native"/>
        </id>
        <property name="name" length="20"/>
        <property name="description" length="50"/>

        <!--
            table表示中间表
        -->
        <set name="courses" table="student_course" cascade="save-update">
            <!--
                表示student在第三方表所对应外键
            -->
            <key>
                <column name="sid"></column>
            </key>
            <many-to-many class="com.xuweiwei.vo.Course" column="cid"> </many-to-many>
        </set>
        
    </class>
</hibernate-mapping>
  • Course.java
package com.xuweiwei.vo;

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

public class Course 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;
    }
}
  • Course.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.Course">
        <id name="cid" length="5">
            <generator class="native"/>
        </id>
        <property name="name" length="20"/>
        <property name="description" length="50"/>
        
        <set name="students" table="student_course">
            <key>
                <column name="cid"></column>
            </key>
            <many-to-many class="com.xuweiwei.vo.Student" column="sid"> </many-to-many>
        </set>
        
    </class>
</hibernate-mapping>
  • 测试代码:
package com.xuweiwei.test;


import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class TestManyToMany {
    
    @Test
    public void testCreateTable(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        
        tx.commit();
        
    }

    



}

 

3.2 多对多的操作

  • 示例:保存学生信息的同时级联保存课程信息
/**
     * 保存学生的同时保存课程
     */
    @Test
    public void testCreateStudentAndCourse(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Student student = new Student();
        student.setName("许威威");
        student.setDescription("java开发");

        Course course1 = new Course();
        course1.setName("Linux");
        course1.setDescription("Linux如此之牛逼");

        Course course2 = new Course();
        course2.setName("java");
        course2.setDescription("java就是如此之牛逼");


        Set<Course> courses = new HashSet<>();
        courses.add(course1);
        courses.add(course2);
        student.setCourses(courses);

        session.save(student);

        tx.commit();
    }

 

  • 示例:解除课程1和所有学生的关系
   //解除课程1和所有学生的关系
    @Test
    public void testRealseAll(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Course course = (Course) session.get(Course.class,1L);

        course.setStudents(null);




        tx.commit();


    }

 

  • 示例:将学生从课程2转到课程1
    /**
     * 将学生从课程2转到课程1
     */
    @Test
    public void testStudentFromCourse2ToCourse1(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        //获取学生
        Student student = (Student) session.get(Student.class,1L);

        //获取课程1和课程2
        Course course1 = (Course) session.get(Course.class,1L);
        Course course2 = (Course) session.get(Course.class,2L);

        //从学生中解除课程2的关系
        student.getCourses().remove(course2);
        //将学生转到课程1
        student.getCourses().add(course1);



        tx.commit();


    }

 

  • 示例:删除学生
/**
     * 删除学生(并解除和课程的关系)
     */
    @Test
    public void testDeleteStudent(){

        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        //获取学生
        Student student = (Student) session.get(Student.class,1L);

        session.delete(student);

        tx.commit();

    }

 

4 一对一操作

  •  以人和身份证为例

 

4.1 环境的搭建

  • hiberante.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://47.93.11.136: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/Person.hbm.xml"/>
    <mapping resource="com/xuweiwei/vo/Identification.hbm.xml"/>
    
</session-factory>
</hibernate-configuration>
  • Person.java
package com.xuweiwei.vo;

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

/**
 * 人
 */
public class Person implements Serializable {
    private Long pid;
    private String name;
    private String sex;


    private Set<Identification> identifications;

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Set<Identification> getIdentifications() {
        return identifications;
    }

    public void setIdentifications(Set<Identification> identifications) {
        this.identifications = identifications;
    }
}
  • Person.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.Person">
        <id name="pid">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <property name="sex"/> 

        <set name="identifications" cascade="save-update">
            <key column="pid"/>
            <one-to-many class="com.xuweiwei.vo.Identification"/>
        </set>

    </class>
</hibernate-mapping>
  • Identification.java
package com.xuweiwei.vo;

/**
 * 身份证
 */
public class Identification {
    private Long iid;
    private String name;

    private Person person;

    public Long getIid() {
        return iid;
    }

    public void setIid(Long iid) {
        this.iid = iid;
    }

    public String getName() {
        return name;
    }

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

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}
  • Identification.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.Identification">
        <id name="iid">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <!--
            unique外键唯一约束
        -->
        <many-to-one name="person" class="com.xuweiwei.vo.Person" unique="true" column="pid"/>
    </class>
</hibernate-mapping>

 

4.2 一对一的操作

  • 保存人信息的同时级联保存身份证信息
    @Test
    public void savePersonAndIdentification(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Person p = new Person();
        p.setName("许威威");
        p.setSex("男");

        Identification identification = new Identification();
        identification.setName("许威威的身份证");



        Set<Identification> identifications = new HashSet<>();
        identifications.add(identification);

        p.setIdentifications(identifications);


        session.save(p);

        tx.commit();

    }

 

5 二级缓存

5.1 二级缓存的数据特点

  • 公共的数据
  • 不经常修改的数据
  • 私密性不是很高的数据

 

5.2 二级缓存的生命周期

  • 二级缓存的生命周期和SessionFactory紧密关联,当Hibernate容器启动的时候,二级缓存开始启动,当Hiberante容器卸载的时候,二级缓存停止。

 

5.3 二级缓存的分类(根据位置区分)

  • 类级别的二级缓存
  • 集合级别的二级缓存

 

5.4 Hibernate开启二级缓存的步骤

  • Hibernate内部没有实现二级缓存,使用的是第三方缓存,所以需要配置

 

  • 环境:班级和学生
    • 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://47.93.11.136: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;
    }
}
    • 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">
            <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;
    }
}
    • 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>

 

  • 步骤:
  • ①在hibernate.cfg.xml中配置二级缓存的供应商
    <!--
        提供二级缓存的供应商
    -->
    <property name="cache.provider_class">
        org.hibernate.cache.EhCacheProvider
    </property>
  • ②在hibernate.cfg.xml中开启二级缓存
    <!--
        开启二级缓存
    -->
    <property name="cache.use_second_level_cache">true</property>
    • 开启类级别的二级缓存
      • 在hibernate.cfg.xml中配置(不推荐)  
     <!--
            开启类级别的二级缓存
            usage,开启二级缓存的策略
                read-only 只读,把一个对象放入到二级缓存中不可以修改
                read-write 读写 把一个对象放入到二级缓存中可以修改
            class:类的全名
        -->
    <class-cache class="com.xuweiwei.vo.Classes" usage="read-only"/>
      • 在对应的映射文件中配置  
<?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">
        <cache usage="read-only"/>
        <id name="cid">
            <generator class="increment"/>
        </id>
        <property name="name"/>
        <property name="description"/>

        <set name="students">
            <key>
                <column name="cid"/>
            </key>
            <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>
    • 开启集合级别的二级缓存
      • 在<set>元素下配置    
<?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">
            <cache usage="read-only"/>
            <key>
                <column name="cid"/>
            </key>
            <one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

 

  • ④测试和使用
    • 类级别的二级缓存  
      • 证明二级缓存的存在  
    /**
     * 先从一级缓存中查找数据,再从二级缓存中查找数据,最后从数据库中查找数据,然后将数据放入到一级缓存和二级缓存
     */
   @Test
   public void testGet(){
       Configuration configuration = new Configuration().configure();
       SessionFactory sessionFactory = configuration.buildSessionFactory();
       Session session = sessionFactory.openSession();

       Classes classes1 = (Classes) session.get(Classes.class,1L);

       session.close();//一级缓存的数据没有了

       session = sessionFactory.openSession();
       Classes classes2 = (Classes) session.get(Classes.class,1L);//没有发出SQL语句
       session.close();

   }
      • 在二级缓存的缓存策略是read-only的情况下,如果你修改数据,会报错    
 @Test
   public void testGet(){
       Configuration configuration = new Configuration().configure();
       SessionFactory sessionFactory = configuration.buildSessionFactory();
       Session session = sessionFactory.openSession();
      Transaction tx =  session.beginTransaction();

       Classes classes1 = (Classes) session.get(Classes.class,1L);
       classes1.setDescription("aa");
       tx.commit();
       session.close();



   }

技术分享图片

    • 集合级别的二级缓存
      • 证明二级缓存的存在    
@Test
    public void testCollection(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx =  session.beginTransaction();

        Classes classes1 =  (Classes) session.get(Classes.class,1L);
        Set<Student> students =  classes1.getStudents();
        for(Student s:students){
            System.out.println(s.getName()+":"+s.getDescription());
        }
        System.out.println(sessionFactory.getStatistics().getCollectionLoadCount());


        tx.commit();
        session.close();

    }

 

5.5 将二级缓存保存到磁盘上

  • 在src下配置ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
         
    <diskStore path="e:\\\\TEMP1"/>
    <defaultCache
            maxElementsInMemory="12"
            eternal="false"
            timeToIdleSeconds="1200"
            timeToLiveSeconds="1200"
            overflowToDisk="false"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
            
       <Cache
            name="com.xuweiwei.vo.Classes"
            maxElementsInMemory="3" 
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
</ehcache>

 

以上是关于Hibernate 的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate的HQL多表查询

使用反射在外部JAR / CLASS上调用包含Hibernate事务的方法(Java EE)

Hibernate CriteriaQuery where - ManyToOne 字段

Hibernate + MySQL:如何为数据库和表设置编码 utf-8

hibernate在使用getCurrentSession时提示no session found for current thread

Java类型相互转换byte[]类型,blob类型