zoukankan      html  css  js  c++  java
  • Hibernate学习(四)

    一对多测试案例

    1、类图

     2、创建表

    复制代码
    drop table if exists t_student ;
    
    drop table if exists t_class ;
    
    create table t_class (
        id int(5) primary key ,
        name varchar(150)
    ) ;
    
    create table t_student (
        id int(10) primary key ,
        name varchar(150) ,
        class_id int(5) ,
        foreign key ( class_id ) references t_class( id )
    ) ;
    
    insert into t_class ( id , name ) values ( 1 , '计算机一班' );
    insert into t_class ( id , name ) values ( 2 , '计算机二班' );
    insert into t_class ( id , name ) values ( 3 , '网络一班' );
    insert into t_class ( id , name ) values ( 4 , '网络二班' );
    
    insert into t_student ( id , name , class_id ) values ( 1 , '张翠山' , 2);
    insert into t_student ( id , name , class_id ) values ( 2 , '曾阿牛' , 2 );
    insert into t_student ( id , name , class_id ) values ( 3 , '赵敏' , 1 );
    insert into t_student ( id , name , class_id ) values ( 4 , '小昭'  , 3 );
    复制代码

    3、持久化类

    班级类:

    package ecut.onetomany.entity;
    
    import java.io.Serializable;
    import java.util.Set;
    
    public class Clazz implements Serializable {
        
        private static final long serialVersionUID = 235617966763001653L;
        
        private Integer id;
        private String name;
        
        // 当前的班级都有那些学生
        private Set<Student> students; // 维护从 班级( one ) 到 学生( many ) 的 一对多 关联关系
        
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Set<Student> getStudents() {
            return students;
        }
    
        public void setStudents(Set<Student> students) {
            this.students = students;
        }
    
    }

    班级类中使用students来使班级和学生相关联

    学生类:

    package ecut.onetomany.entity;
    
    import java.io.Serializable;
    
    public class Student  implements Serializable {
    
        private static final long serialVersionUID = 399214402506858645L;
        
        private Integer id;
        private String name;
        
        public Student() {
            super();
        }
        
        public Student(String name) {
            super();
            this.name = name;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    }

    4、映射文件

    班级映射文件:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
    
        <class name="ecut.onetomany.entity.Clazz" table="t_class">
        
            <id name="id" type="integer" column="id" >
                <generator class="increment" /> 
            </id>
        
            <property name="name" type="string" column="name" />
            
            <!-- 使用 set 标记 映射 Set 集合 , name 属性指定 实体类中的 Set 集合的名称,order-by 所对应的表中的列名 -->
            <set name="students" order-by="id ASC"  cascade="all" >
                <!-- 使用 key 的 column 属性指定 对方 ( many 一方 ) 表中 参照 当前表 ( t_class ) 的主键的那个外键的名称 -->
                <key column="class_id" />
                <!-- 指定 对方  ( many 一方 )  的类型 ( Set 集合中存放的元素的类型 )  -->
                <one-to-many class="ecut.onetomany.entity.Student" />
            </set>
        
        </class>
        
    </hibernate-mapping>

    学生映射文件:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
    
        <class name="ecut.onetomany.entity.Student" table="t_student">
        
            <id name="id" type="integer" column="id" >
                <generator class="increment" /> 
            </id>
        
            <property name="name" type="string" column="name" />
            
        </class>
        
    </hibernate-mapping>

    5、hibernate配置文件

    <?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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF8</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">123456</property>
            
            <!-- 设置事务隔离级别 , 取值可以是 1、2、4、8 -->
            <property name="hibernate.connection.isolation">1</property>
            <!-- 设置事务是否自动提交 , 取值可以是 true 、false -->
            <property name="hibernate.connection.autocommit">false</property>
            
            <!-- 指定数据方言类 -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
            
            <!-- 指示是否显示 执行过的 SQL 语句 -->
            <property name="hibernate.show_sql">true</property>
            <!-- 指示是否对 SQL 语句进行格式化输出 -->
            <property name="hibernate.format_sql">false</property>
            
            <mapping resource="ecut/onetomany/entity/Clazz.hbm.xml"/>
            <mapping resource="ecut/onetomany/entity/Student.hbm.xml"/>
            
        </session-factory>
    
    </hibernate-configuration>

    6、测试类

    从数据库中获取一个班级对象,之后获得所属学生的集合:

    package ecut.onetomany.test;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import ecut.onetomany.entity.Clazz;
    import ecut.onetomany.entity.Student;
    
    public class TestOneToMany {
        private SessionFactory factory ;
        private Session session ; 
        
        public @Before void init() {
            // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
            Configuration config = new Configuration();
            // 读取配置文件
            config.configure("ecut/onetomany/hibernate.cfg.xml");
            //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件
    
            // 使用 Configuration 创建 SessionFactory
            factory = config.buildSessionFactory();
            
            // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
            session = factory.openSession();
        }
        
        public @Test void loadClazz(){
            
            Clazz c = session.find( Clazz.class ,  2 );
            
            if( c == null ){
                System.out.println( "没有找到对应的班级" );
            } else {
                System.out.println( c.getId() + " : " + c.getName() );
                
                Set<Student> students = c.getStudents(); // <set name="students" order-by="id DESC" >
                
                System.out.println( students.getClass() );
                
                if( students == null || students.isEmpty() ) {
                    System.out.println( c.getName() + "还没有学生");
                } else {
                    for( Student s : students ){
                        System.out.println( "	" + s.getId() + " : " + s.getName() );
                    }
                }
                
            }
            
            
        }public @After void destory(){
            session.close();
            factory.close();
        }
    
    }

    班级持久化类中的set是PersistentSet类其中可以排序,可以在班级映射文件中的set标签中指定order-by属性来给学生排序。

        <!-- 使用 set 标记 映射 Set 集合 , name 属性指定 实体类中的 Set 集合的名称,order-by 所对应的表中的列名 -->
            <set name="students" order-by="id ASC"  cascade="all" >

    保存一个新创建的班级对象到数据库,并为其添加学生,将学生一起保存:

    package ecut.onetomany.test;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import ecut.onetomany.entity.Clazz;
    import ecut.onetomany.entity.Student;
    
    public class TestOneToMany {
        private SessionFactory factory ;
        private Session session ; 
        
        public @Before void init() {
            // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
            Configuration config = new Configuration();
            // 读取配置文件
            config.configure("ecut/onetomany/hibernate.cfg.xml");
            //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件
    
            // 使用 Configuration 创建 SessionFactory
            factory = config.buildSessionFactory();
            
            // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
            session = factory.openSession();
        }
        public @Test void saveClazz(){ 
            
            Clazz c = new Clazz();
            c.setName( "华山派" );
            
            Set<Student> students = new HashSet<>();
            
            Student s1 = new Student( "令狐冲" ) ;
            students.add( s1 );
            
            Student s2 = new Student( "岳灵珊" ) ;
            students.add( s2 );
            
            Student s3 = new Student( "陆大有" ) ;
            students.add( s3 );
            
            Student s4 = new Student( "林平之" ) ;
            students.add( s4 );
    
            c.setStudents( students ); // 确定 班级中都有哪些 学生
            
            session.getTransaction().begin();
            session.save( c ); // <set name="students" cascade="all" >
            session.getTransaction().commit();
            
        }
        
        public @After void destory(){
            session.close();
            factory.close();
        }
    
    }

    运行结果:

    Hibernate: select max(id) from t_class
    Hibernate: select max(id) from t_student
    Hibernate: insert into t_class (name, id) values (?, ?)
    Hibernate: insert into t_student (name, id) values (?, ?)
    Hibernate: insert into t_student (name, id) values (?, ?)
    Hibernate: insert into t_student (name, id) values (?, ?)
    Hibernate: insert into t_student (name, id) values (?, ?)
    Hibernate: update t_student set class_id=? where id=?
    Hibernate: update t_student set class_id=? where id=?
    Hibernate: update t_student set class_id=? where id=?
    Hibernate: update t_sent set class_id=? where id=?

    是先保存class然后再保存student,并通过update语句来指定班级号。

    若没有在映射文件中的set标签指定cascade属性则会抛出java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance beforeQuery flushing:的异常,为了解决这个异常,可以在保存class前先保存一下student,或者是通过指定cascade属性来完成级联保存class的对象同时会把关联的瞬时状态的对象student也保存。

        <!-- 使用 set 标记 映射 Set 集合 , name 属性指定 实体类中的 Set 集合的名称,order-by 所对应的表中的列名 -->
            <set name="students" order-by="id ASC"  cascade="all" >

    转载请于明显处标明出处:

    https://www.cnblogs.com/AmyZheng/p/9317570.html

  • 相关阅读:
    Yield Usage Understanding
    Deadclock on calling async methond
    How to generate file name according to datetime in bat command
    Run Unit API Testing Which Was Distributed To Multiple Test Agents
    druid的关键参数+数据库连接池运行原理
    修改idea打开新窗口的默认配置
    spring boot -thymeleaf-url
    @pathvariable和@RequestParam的区别
    spring boot -thymeleaf-域对象操作
    spring boot -thymeleaf-遍历list和map
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9317570.html
Copyright © 2011-2022 走看看