• Hibernate(六)一对多映射(多对一)


    一、Hinbernate中持久化类的关联关系

    在数据库中,表表之间是通过外键关联的,在程序中是要转化为持久化类也就是(JAVA Bean)来实例的。

    但在Hibernater中持久化的之间的映射关系,不是通外键建立关联,而是通过属性.主要有以下几种

    • 一对一,
    • 一对多(多对一)
    • 多对多

    关联方向:

    • 单向关联
    • 双向关联

    二、一对多单向关联关系

    2.1、建立数据库表

    班级表,和学生表,学生生通过班级表中的,班级编号为外键

    --班级表
    create table grade
    (
           gid       number           primary key,  --班级ID
           gname     varchar2(50),                  --班级名称
           gdesc     varchar2(50)                   --班级介绍
    );
    --学生表
    create table student
    (
           sid       number           primary key,  --主键ID学生ID
           sname     varchar2(20),            --学生姓名
           sex       varchar2(20),            --学生性别
           gid       number           references grade(gid) ---外键班级ID
    );

    2.2、建立持久化类和映射配置文件

    班级和学生类

    package entity;
    
    
    import java.util.HashSet;
    import java.util.Set;
    
    
    /*
     * 班级类
     */
    public class Grade implements java.io.Serializable {
    
        // Fields
        private static final long serialVersionUID = 1L;
        private int gid;
        private String gname;
        private String gdesc;
        private Set<Student> students = new HashSet<Student> ();
    
        // Constructors
    
        /** default constructor */
        public Grade() {
        }
    
        /** minimal constructor */
        public Grade(int gid) {
            this.gid = gid;
        }
    
        /** full constructor */
        public Grade(int gid, String gname, String gdesc, Set<Student> students) {
            this.gid = gid;
            this.gname = gname;
            this.gdesc = gdesc;
            this.students = students;
        }
    
        // Property accessors
    
        public int getGid() {
            return this.gid;
        }
    
        public void setGid(int gid) {
            this.gid = gid;
        }
    
        public String getGname() {
            return this.gname;
        }
    
        public void setGname(String gname) {
            this.gname = gname;
        }
    
        public String getGdesc() {
            return this.gdesc;
        }
    
        public void setGdesc(String gdesc) {
            this.gdesc = gdesc;
        }
    
        public Set<Student> getStudents() {
            return this.students;
        }
    
        public void setStudents(Set<Student> students) {
            this.students = students;
        }
    
    }
    View Code

    学生类

    package entity;
    
    /*
     * 学生类
     */
    public class Student implements java.io.Serializable {
    
        // Fields
    
        private static final long serialVersionUID = 1L;
        private int sid;
        
        private String sname;
        private String sex;
    
        // Constructors
    
        /** default constructor */
        public Student() {
        }
    
        /** minimal constructor */
        public Student(int sid) {
            this.sid = sid;
        }
    
        /** full constructor */
        public Student(int sid, String sname, String sex ) {
        
            this.sid = sid;
    
            this.sname = sname;
            this.sex = sex;
        }
    
        // Property accessors
    
        public int getSid() {
            return this.sid;
        }
    
        public void setSid(int sid) {
            this.sid = sid;
        }
    
        
    
        public String getSname() {
            return this.sname;
        }
    
        public void setSname(String sname) {
            this.sname = sname;
        }
    
        public String getSex() {
            return this.sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
    }
    View Code

    hibernate.cf.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>
    
    <session-factory>
        <property name="dialect">
            org.hibernate.dialect.Oracle9Dialect
        </property>
        <property name="connection.url">
            jdbc:oracle:thin:@localhost:1521:orcl
        </property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
        <property name="connection.driver_class">
            oracle.jdbc.OracleDriver
        </property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
    
        <mapping resource="entity/Grade.hbm.xml" />
        <mapping resource="entity/Student.hbm.xml" />
    
    </session-factory>
    
    </hibernate-configuration>

    持久类配置先来学生类

    <?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="entity.Student" table="STUDENT" schema="ROOT">
            <id name="sid" type="java.lang.Integer">
                <column name="SID" precision="22" scale="0" />
                <generator class="assigned" />
            </id>
            <property name="sname" type="java.lang.String">
                <column name="SNAME" length="20" />
            </property>
            <property name="sex" type="java.lang.String">
                <column name="SEX" length="20" />
            </property>
        </class>
    </hibernate-mapping>

    班级类配置

    <?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="entity.Grade" table="GRADE" schema="ROOT">
            <id name="gid" type="java.lang.Integer">
                <column name="GID" precision="22" scale="0" />
                <generator class="assigned" />
            </id>
            <property name="gname" type="java.lang.String">
                <column name="GNAME" length="50" />
            </property>
            <property name="gdesc" type="java.lang.String">
                <column name="GDESC" length="50" />
            </property>
            <!--建立set属性,也可以建立list和持久化类中一致就行  -->
            <set name="students">
                <key>
                <!--这里的列是指学生表中的班级编号  -->
                    <column name="GID" precision="22" scale="0" />
                </key>
                <!-- 通过class属性指定set的属性 -->
                <one-to-many class="entity.Student" />
            </set>
        </class>
    </hibernate-mapping>

    测试类

    package Test;
    
    import java.util.Set;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    
    import entity.Grade;
    import entity.Student;
    
    public class Demo1 {
    
        /**
         * 测试类
         */
        public static void main(String[] args) {
            save();
             find();
            update();
    
        }
    
        public static void save() {
            // 声明班级对象,并赋值
            Grade grade = new Grade();
            grade.setGid(201504);
            grade.setGname("Java一班");
            grade.setGdesc("刚开始学习JAVA");
            // 声明2个学生对象
            Student stu1 = new Student();
            stu1.setSid(201504012);
            stu1.setSname("张三");
            stu1.setSex("男");
    
            Student stu2 = new Student();
            stu2.setSid(201504013);
            stu2.setSname("李四");
            stu2.setSex("女");
    
            // 将学生添加到班级
            grade.getStudents().add(stu1);
            grade.getStudents().add(stu2);
            // 建立session
            Session session = new Configuration().configure().buildSessionFactory()
                    .openSession();
            // 开始事务
            Transaction transaction = session.beginTransaction();
            // 保存班级
            session.save(grade);
            // 保存学生
            session.save(stu1);
            session.save(stu2);
            // 提交事务
            transaction.commit();
            // 关闭session
            session.close();
        }
    
        /*
         * 将基中一个学生更改为别一个班级
         */
        public static void update() {
            // 声明班级对象,并赋值
            Grade grade = new Grade();
            grade.setGid(201506);
            grade.setGname("Java二班");
            grade.setGdesc("学习JAVA二年级");
            // 获取一个学生的信息
            // 建立session
            Session session = new Configuration().configure().buildSessionFactory()
                    .openSession();
            // 开始事务
            Transaction transaction = session.beginTransaction();
            Student stu1=(Student) session.get(Student.class, 201504013);
            //将学生添加到这个新的班级
            grade.getStudents().add(stu1);
            // 保存班级
            session.save(grade);
            // 保存学生
            session.save(stu1);
            // 提交事务
            transaction.commit();
            // 关闭session
            session.close();
        }
    
        // 查询班级
        public static void find() {
    
            // 建立session
            Session session = new Configuration().configure().buildSessionFactory()
                    .openSession();
            Grade g = (Grade) session.get(Grade.class, 201504);
            System.out.println("班级信息:" + g.getGid() + "	" + g.getGname()
                    + g.getGdesc());
            // 通过班级获取这个班级的学生信息
            System.out.println("201504班的学生信息如下:");
            Set<Student> set = g.getStudents();
            for (Student stu : set) {
                System.out.println(stu.getSid() + "	" + stu.getSname() + "	"
                        + stu.getSex());
            }
        }
    
    }

    以上只上单向关联,一般都会有双向关联

    同样要在学生类中添加Grade 属性

    在学生类的配置文件中配置关联字段

     二、建立双向关联

    2.1、更改学生类和配置文件

    package entity;
    
    /*
     * 学生类
     */
    public class Student implements java.io.Serializable {
    
        // Fields
    
        private static final long serialVersionUID = 1L;
        private int sid;
        private String sname;
        private String sex;
        //增加班级属性
        private Grade grade;
    
        // Constructors
    
        /** default constructor */
        public Student() {
        }
    
        /** minimal constructor */
        public Student(int sid) {
            this.sid = sid;
        }
    
        /** full constructor */
        public Student(int sid, String sname, String sex ) {
        
            this.sid = sid;
    
            this.sname = sname;
            this.sex = sex;
        }
    
        // Property accessors
    
        public int getSid() {
            return this.sid;
        }
    
        public void setSid(int sid) {
            this.sid = sid;
        }
    
        
    
        public String getSname() {
            return this.sname;
        }
    
        public void setSname(String sname) {
            this.sname = sname;
        }
    
        public String getSex() {
            return this.sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Grade getGrade() {
            return grade;
        }
    
        public void setGrade(Grade grade) {
            this.grade = grade;
        }
        
    
    }

    配置文件 

    <?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="entity.Student" table="STUDENT" schema="ROOT">
            <id name="sid" type="java.lang.Integer">
                <column name="SID" precision="22" scale="0" />
                <generator class="assigned" />
            </id>
            <property name="sname" type="java.lang.String">
                <column name="SNAME" length="20" />
            </property>
            <property name="sex" type="java.lang.String">
                <column name="SEX" length="20" />
            </property>
            <!--配置grade属性  -->
            <many-to-one name="grade" class="entity.Grade">
            <!--指定学生表中的外键  -->
            <column name="GID" />
            </many-to-one>
        </class>
    </hibernate-mapping>

    2.2、测试类

    建立双向关联后,就可以通过学生来获取班级信息

    清空数据表中的数据

    package Test;
    
    import org.hibernate.Session;
    import org.hibernate.cfg.Configuration;
    
    import entity.Student;
    
    public class Demo2 {
    
        /**
         * 测试类
         */
        public static void main(String[] args) {
     save();
    findByStu();
        }
        
        public static void findByStu(){
            Session session = new Configuration().configure().buildSessionFactory()
                    .openSession();
            //获取一个学生的信息 get方法为通过主键查询
            Student stu=(Student) session.get(Student.class, 201504013);
            System.out.println("学生信息:	"+stu.getSid()+"	"+stu.getSname()+"	"+stu.getSex());
            //通过学生信息得到班级信息
            System.out.println("这个学生的班级信息:"+stu.getGrade().getGid()+"	"+stu.getGrade().getGname()+"	"+stu.getGrade().getGdesc());
        }
    }
    public static void save() {
    // 声明班级对象,并赋值
    Grade grade = new Grade();
    grade.setGid(201504);
    grade.setGname("Java一班");
    grade.setGdesc("刚开始学习JAVA");
    // 声明2个学生对象
    Student stu1 = new Student();
    stu1.setSid(201504012);
    stu1.setSname("张三");
    stu1.setSex("男");
    stu1.setGrade(grade);
    
    
    Student stu2 = new Student();
    stu2.setSid(201504013);
    stu2.setSname("李四");
    stu2.setSex("女");
    stu2.setGrade(grade);
    // 将学生添加到班级
    /*grade.getStudents().add(stu1);
    grade.getStudents().add(stu2);*/
    // 建立session
    Session session = new Configuration().configure().buildSessionFactory()
    .openSession();
    // 开始事务
    Transaction transaction = session.beginTransaction();
    // 保存班级
    session.save(grade);
    // 保存学生
    session.save(stu1);
    session.save(stu2);
    // 提交事务
    transaction.commit();
    // 关闭session
    session.close();
    }

    三、级联保存和删除

    能不能只保存学生时,同时保存班级呢,或者保存班级时,同时保存学生呢

    3.1、cascade属性

     

    保存班级时,同时保存学生信息

    修改班级配置,在set标签中添加cascade属性,设置为save-update

    <?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="entity.Grade" table="GRADE" schema="ROOT">
            <id name="gid" type="java.lang.Integer">
                <column name="GID" precision="22" scale="0" />
                <generator class="assigned" />
            </id>
            <property name="gname" type="java.lang.String">
                <column name="GNAME" length="50" />
            </property>
            <property name="gdesc" type="java.lang.String">
                <column name="GDESC" length="50" />
            </property>
            <!--建立set属性,也可以建立list和持久化类中一致就行  -->
            <set name="students" cascade="save-update">
                <key>
                <!--这里的列是指学生表中的班级编号  -->
                    <column name="GID" precision="22" scale="0" />
                </key>
                <!-- 通过class属性指定set的属性 -->
                <one-to-many class="entity.Student" />
            </set>
        </class>
    </hibernate-mapping>

    测试类

    package Test;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    
    import entity.Grade;
    import entity.Student;
    
    public class Demo3 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            save();
    
        }
        public static void save() {
            // 声明班级对象,并赋值
            Grade grade = new Grade();
            grade.setGid(201504);
            grade.setGname("Java一班");
            grade.setGdesc("刚开始学习JAVA");
            // 声明2个学生对象
            Student stu1 = new Student();
            stu1.setSid(201504012);
            stu1.setSname("张三");
            stu1.setSex("男");
            stu1.setGrade(grade);
            
            
            Student stu2 = new Student();
            stu2.setSid(201504013);
            stu2.setSname("李四");
            stu2.setSex("女");
            stu2.setGrade(grade);
            // 将学生添加到班级
            grade.getStudents().add(stu1);
            grade.getStudents().add(stu2);
            // 建立session
            Session session = new Configuration().configure().buildSessionFactory()
                    .openSession();
            // 开始事务
            Transaction transaction = session.beginTransaction();
            // 保存班级
            session.save(grade);
            // 保存学生
            //session.save(stu1);
            //session.save(stu2);
            // 提交事务
            transaction.commit();
            // 关闭session
            session.close();
        }
    }

    反之,在学生类的配置文件one-many中添加cascade属性设置为save-update

    <?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="entity.Student" table="STUDENT" schema="ROOT">
            <id name="sid" type="java.lang.Integer">
                <column name="SID" precision="22" scale="0" />
                <generator class="assigned" />
            </id>
            <property name="sname" type="java.lang.String">
                <column name="SNAME" length="20" />
            </property>
            <property name="sex" type="java.lang.String">
                <column name="SEX" length="20" />
            </property>
            <!--配置grade属性  -->
            <many-to-one name="grade" class="entity.Grade" cascade="save-update">
            <!--指定学生表中的外键  -->
            <column name="GID" />
            </many-to-one>
        </class>
    </hibernate-mapping>
    package Test;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    
    import entity.Grade;
    import entity.Student;
    
    public class Demo3 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            save();
    
        }
        public static void save() {
            // 声明班级对象,并赋值
            Grade grade = new Grade();
            grade.setGid(201504);
            grade.setGname("Java一班");
            grade.setGdesc("刚开始学习JAVA");
            // 声明2个学生对象
            Student stu1 = new Student();
            stu1.setSid(201504012);
            stu1.setSname("张三");
            stu1.setSex("男");
            stu1.setGrade(grade);
            
            
            Student stu2 = new Student();
            stu2.setSid(201504013);
            stu2.setSname("李四");
            stu2.setSex("女");
            stu2.setGrade(grade);
            // 将学生添加到班级
            grade.getStudents().add(stu1);
            grade.getStudents().add(stu2);
            // 建立session
            Session session = new Configuration().configure().buildSessionFactory()
                    .openSession();
            // 开始事务
            Transaction transaction = session.beginTransaction();
            // 保存班级
            //session.save(grade);
            // 保存学生
            session.save(stu1);
            session.save(stu2);
            // 提交事务
            transaction.commit();
            // 关闭session
            session.close();
        }
    }
    View Code

    3.2、inverse属性

     

    首先在班级类中设置invers属性为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="entity.Grade" table="GRADE" schema="ROOT">
            <id name="gid" type="java.lang.Integer">
                <column name="GID" precision="22" scale="0" />
                <generator class="assigned" />
            </id>
            <property name="gname" type="java.lang.String">
                <column name="GNAME" length="50" />
            </property>
            <property name="gdesc" type="java.lang.String">
                <column name="GDESC" length="50" />
            </property>
            <!--建立set属性,也可以建立list和持久化类中一致就行  -->
            <set name="students" cascade="save-update" inverse="false">
                <key>
                <!--这里的列是指学生表中的班级编号  -->
                    <column name="GID" precision="22" scale="0" />
                </key>
                <!-- 通过class属性指定set的属性 -->
                <one-to-many class="entity.Student" />
            </set>
        </class>
    </hibernate-mapping>
    View Code

    测试类

    package Test;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    
    import entity.Grade;
    import entity.Student;
    
    public class Demo4 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            delete() ;
    
        }
    
        public static void delete() {
            
            // 建立session
            Session session = new Configuration().configure().buildSessionFactory()
                    .openSession();
            // 开始事务
            Transaction transaction = session.beginTransaction();
            // 保存班级
            Grade grade=(Grade) session.get(Grade.class, 201504);
            // 保存学生
            session.delete(grade);
            // 提交事务
            transaction.commit();
            // 关闭session
            session.close();
        }
    }
    View Code

    结果:发现班级表中的班级已经删除,而学生表中数据没有删除,只是GID字段为NULL

    下面将inverse设置为true时,添加新学生,和新的班级

    <?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="entity.Grade" table="GRADE" schema="ROOT">
            <id name="gid" type="java.lang.Integer">
                <column name="GID" precision="22" scale="0" />
                <generator class="assigned" />
            </id>
            <property name="gname" type="java.lang.String">
                <column name="GNAME" length="50" />
            </property>
            <property name="gdesc" type="java.lang.String">
                <column name="GDESC" length="50" />
            </property>
            <!--建立set属性,也可以建立list和持久化类中一致就行  -->
            <set name="students" cascade="save-update" inverse="true">
                <key>
                <!--这里的列是指学生表中的班级编号  -->
                    <column name="GID" precision="22" scale="0" />
                </key>
                <!-- 通过class属性指定set的属性 -->
                <one-to-many class="entity.Student" />
            </set>
        </class>
    </hibernate-mapping>
    View Code

    测试类

    package Test;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    
    import entity.Grade;
    import entity.Student;
    
    public class Demo4 {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            delete() ;
    
        }
    
        public static void delete() {
            
            // 声明班级对象,并赋值
                    Grade grade = new Grade();
                    grade.setGid(201509);
                    grade.setGname("Java三班");
                    grade.setGdesc("ASP.NET");
                    // 声明2个学生对象
                    Student stu1 = new Student();
                    stu1.setSid(201509009);
                    stu1.setSname("王五");
                    stu1.setSex("女");
                    stu1.setGrade(grade);
                    
                    Student stu2 = new Student();
                    stu2.setSid(201509045);
                    stu2.setSname("赵六");
                    stu2.setSex("女");
                    stu2.setGrade(grade);
            
            // 建立session
            Session session = new Configuration().configure().buildSessionFactory()
                    .openSession();
            // 开始事务
            Transaction transaction = session.beginTransaction();
        
            
            // 保存学生
            session.save(stu1);
            session.save(stu2);
            // 提交事务
            transaction.commit();
            // 关闭session
            session.close();
        }
    }
    View Code

    结果发现,我并没有用班级添加学生,也没有保存班级,只是保存了学生,班级信息一起保存了 

  • 相关阅读:
    SDNU 1123.Encoding
    SDNU 1120.ISBN号码
    SDNU 1119.Intelligent IME(水题)
    SDNU 1115.谁拿了最多奖学金(水题)
    解决Docker运行命令时提示"Got permission denied while trying to connect to the Docker daemon socket"类情况
    jupyter notebook修改默认浏览器
    CentOS切换用户命令su or su+username
    图像内插,双线性插值等
    python求最大公约数和最小公倍数
    Python split()方法
  • 原文地址:https://www.cnblogs.com/liunanjava/p/4336126.html
Copyright © 2020-2023  润新知