• 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

  • 相关阅读:
    Android学习 反编译APK文件
    全面剖析C#之String对象
    Retrieving the COM class factory for component with CLSID {0006F03A00000000C000000000000046} failed due to the following error: 80080005
    面向对象的函数式编程语言Scala 简介安装
    Export/Import相关操作
    Windows Server 2008 R2(64位)下安装SQL Server 2005
    C#操作FTP总结
    Windows Server 2008 R2(64位)下IIS7.5操作
    Quartz.Net 学习随手记之01 初步介绍
    差分约束系统
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9317570.html
Copyright © 2020-2023  润新知