zoukankan      html  css  js  c++  java
  • hibernate入门三之关联映射(一对多和多对一)

    提示;本文的操作是在入门一和二上面的

    hibernate对映射类型

    在开始是学习的时候,我以为一对多和多对一是同样的,后来发现不是这样,比如说班主任和班级里的学生,一个班级可能有多个学生,但是只有一个班主任,学生和班主任的关系是多对一,班主任和学生的关系是一对多,两者之间的区别在于它们的指向性

    • 一对一(one-to-one )
    • 一对多(ont-to-many)
    • 多对一(many-to-one)
    • 多对多(many-to-many)

    一对多(ont-to-many)和多对一(many-to-one)最常见和做常用的映射类型

    一对多(ont-to-many)

    1、创建班级表和学生表,通过外键进行关联(

    alter table Students add constraint fk_students_gid foreign key (gid) references grade(gid);

    2、创建班级表和学生表的实体类(属性/默认构造器、带参构造器、get和set方法,toString方法)

    private int gid;
    private String gname;
    private String gdesc;
    // 在一方定义一个多方的集合
    private Set<Students> students = new HashSet<Students>();
    //其他。。。略 }
    public class Students {
    
        private int sid;
        private String sname;
        private String gender;
        private Date birthday;
        //private String address;
        private Blob pictur;
        private Address address;
    
    //其他。。。略
    }
    

     3、创建Grade.hbm.xml(我的Stuendt.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.hibernate.entity.Grade" table="grade">
            <id name="gid" column="gid" type="int">
                <generator class="increment"></generator>
            </id>
            <property name="gname" type="java.lang.String">
                <column name="gname"/>
            </property>
            <property name="gdesc" type="java.lang.String">
                <column name="gdesc"/>
            </property>
            <!--单项的一对多的关系-->
            <set name="students" table="Students">
                <!--指定的关联外键列-->
                <key column="gid"></key>
                <one-to-many class="com.hibernate.entity.Students"/>
            </set>
    
        </class>
    
    
    </hibernate-mapping>
    

     4、在cfg.xml中配置映射文件路径

    <!--指定映射文件的路径-->
        <mapping resource="com/hibernate/entity/Grade.hbm.xml"/>
        <mapping resource="com/hibernate/entity/Students.hbm.xml"/>
    

     5、创建HibernateUtil类

    public class HibernadUtil {
    
        private static SessionFactory sessionFactory;
        private static Session session;
    
        static {
            StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
            sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
        }
    
        //获取SessionFacory
        public static SessionFactory getSessionFacory() {
            return sessionFactory;
        }
    
        //获取session
        public static Session getSession() {
    
            return sessionFactory.openSession();
        }
    
        //关闭session
        public static void closeSession(Session session) {
            if (null != session) {
                session.close();
            }
        }
    

     6、进行测试

    public class TestStudentsAndGrade {
    
        public static void main(String[] args) {
            //add();
            //findStudensByGrade();
            //update();
            deleteStudentsBySid();
        }
    
        //给表中插入数据
        public static void add() {
            Grade grade = new Grade("道班", "道一");
            Students s = new Students("道一", "男", new Date());
            Students s2 = new Students("阴阳", "男", new Date());
            Students s3 = new Students("三生", "女", new Date());
            System.out.println(grade.getStudents().add(s));
            //如果希望在学生表中添加对应道班级编号,需要在班级中添加学生,建立关联关系
            grade.getStudents().add(s);
            grade.getStudents().add(s2);
            grade.getStudents().add(s3);
    
            Session session = HibernadUtil.getSession();
            //开启事务
            Transaction transaction = session.beginTransaction();
            session.save(grade);
            session.save(s);
            session.save(s2);
            session.save(s3);
            transaction.commit();
            HibernadUtil.closeSession(session);
        }
    
        //查询班级中包含的学生
        public static void findStudensByGrade() {
            //获取session
            Session session = HibernadUtil.getSession();
            //获取班级信息
            Grade grade = session.get(Grade.class, 1);
            //输出班级信息
            System.out.println(grade.getGname() + "," + grade.getGdesc());
    
            //找出班级信息,然后找出班级学生信息
            Set<Students> students = grade.getStudents();
            for (Students stu:students
                 ) {
                System.out.println(stu);
            }
        }
    
        //修改学生信息
        public static void update(){
            Grade grade =new Grade("道","道二");
            Session session = HibernadUtil.getSession();
            Transaction transaction = session.beginTransaction();
    
            //修改学生所在班级信息(grade班级信息为自增长,别一不小心玩过头了)
            Students students = session.get(Students.class, 2);
            grade.getStudents().add(students);
            session.save(grade);
            transaction.commit();
            HibernadUtil.closeSession(session);
        }
    
        //从班级中删除学生信息
        public static  void deleteStudentsBySid(){
    
            Session session = HibernadUtil.getSession();
            Transaction transaction = session.beginTransaction();
            Students students = session.get(Students.class,9);
            session.delete(students);
            transaction.commit();
            HibernadUtil.closeSession(session);
    
        }
    
    }
    

     7、一对多中的set元素属性

    多对一(many-to-one)

    描述:多对一多关系和关系数据库中外键的参照关系最匹配,即在已方的表中的一个外键参考另一个表中的主键

    实现:通过多方持有一方的引用实现,需要在“多”的一端使用<many-to-one>配置

    1、在多方定义一个一方的引用,如(private Grade grade;)(属性/默认构造器、带参构造器、get和set方法,toString方法)

    public class Students {
    
        private int sid;
        private String sname;
        private String gender;
        private Date birthday;
        //private String address;
        private Blob pictur;
        private Address address;
        private int gid;
        //在多方定义一个一方的引用
        private Grade grade;
    //其他。。。略

    }

     2、增加配置文件属性(如果有上一步的话,则需要修改相应的属性,删掉grade.hbm.xml中的set元素,在Stuent.hbm.xml中添加<many-to-one>属性)

    友情提示:相比于one-to-many,many-to-one是直接写的,不用添加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.hibernate.entity.Students" table="Students">
            <!--id表示表的主键-->
            <id name="sid" type="int">
                <column name="SID"/>
                <!--表的生成策略-->
                <generator class="native"/>
            </id>
            <property name="sname" type="java.lang.String">
                <column name="SNAME"/>
            </property>
            <property name="gender" type="java.lang.String">
                <column name="GENDER"/>
            </property>
            <property name="birthday" type="time">
                <column name="BIRTHDAY"/>
            </property>
            <property name="pictur" type="java.sql.Blob">
                <column name="PICTUR"/>
            </property>
    
    
            <component name="address" class="com.hibernate.entity.Address" >
               <property name="postcode" column="POSTCODE" type="java.lang.String"/>
                <property name="phone" column="PHONE" type="java.lang.String"/>
                <property name="address" column="ADDRESS" type="java.lang.String"/>
            </component>
    
            <many-to-one name="grade" class="com.hibernate.entity.Grade" column="gid"></many-to-one>
    
        </class>
    

     3、进行测试

    public class TestStudent {
        public static void main(String[] args) {
            save();
        }
    
        //添加学生和班级
        public static void save() {
            Grade grade = new Grade("道班", "道一");
            Students s = new Students("道一", "男", new Date());
            Students s2 = new Students("阴阳", "男", new Date());
            Students s3 = new Students("三生", "女", new Date());
    
            //设置关系
            s.setGrade(grade);
            s2.setGrade(grade);
            s3.setGrade(grade);
    
            Session session = HibernadUtil.getSession();
            Transaction transaction = session.beginTransaction();
            session.save(grade);
            session.save(s);
            session.save(s2);
            session.save(s3);
    
            //提交事务
            transaction.commit();
            //关闭事务
            HibernadUtil.closeSession(session);
        }
    
        
    }
    

    同时配置 一对多(ont-to-many)和多对一(many-to-one)的关系(双向关联关系,可以双向查询,非常方便)

    通过配置两个对应的hbm.xml实现(实体类也需要相应的配置)

    一对多

     <set name="students" table="Students">
                <!--指定的关联外键列-->
                <key column="gid"></key>
                <one-to-many class="com.hibernate.entity.Students"/>
            </set>
    

     多对一

     <many-to-one name="grade" class="com.hibernate.entity.Grade" column="gid"></many-to-one>

    代码关系建立(关系建立之后,执行之后会多出update语句,对性能会有影响,所以需要通过inverse属性去掉这两句话)

     //设置关系(双向关系)
            grade.getStudents().add(s);
            grade.getStudents().add(s2);
            grade.getStudents().add(s3);
            s.setGrade(grade);
            s2.setGrade(grade);
            s3.setGrade(grade);
    

    inverse属性的用法

    • <set>节点的inverse属性指定关联关系的控制方向,默认由one方来维护
    • 关联关系中,inverse=“false”,则为主动方,由主动方负责维护关联关系
    • 在一对多关联中,只能设置one方的inverse为“true”,这将有助于性能改善
    <!--单项的一对多的关系,inverse设置为true,由多方维护关联关系,-->
    <set name="students" table="Students" inverse="true">
    <!--指定的关联外间列-->
    <key column="gid"></key>
    <one-to-many class="com.hibernate.entity.Students"/>
    </set>

     cascade属性(级联操作)

    <!--单项的一对多的关系,inverse设置为true,由多方维护关联关系
            当进行保存和更新时级联操作所关联的对象-->
            <set name="students" table="Students" inverse="true">
                <!--指定的关联外间列-->
                <key column="gid"></key>
                <one-to-many class="com.hibernate.entity.Students"/>
            </set>
    

     相比于之前,只需要写(session.save(grade)就可以了

            session.save(grade);//级联操作,班级对学生

     学生对班级的级联操作配置方案

       <many-to-one name="grade" class="com.hibernate.entity.Grade" column="gid" cascade="all"></many-to-one>
    

     代码端则为

            session.save(s);
            session.save(s2);
            session.save(s3);
           //级联操作,学生对班级

    测试(查询学生所在班级信息)

    public static void findGradeByStudent() {
            Session session = HibernadUtil.getSession();
            //一定要注意你数据里的数据,是否有这个学生id,否则会报错
            Students students = session.get(Students.class, 31);
            System.out.println(students.getSname()+","+students.getGender()+","+students.getBirthday());
    
            Grade grade=students.getGrade();
            System.out.println(grade.getGname()+","+grade.getGdesc());
            HibernadUtil.closeSession(session);
    
        }
    
  • 相关阅读:
    正则表达式
    JavaScript基础
    Servlet监听器
    Java EKT关键技术强化 tomcat中文乱码问题
    spring和springmvc 整合步骤
    [ERROR] [ERROR] Some problems were encountered while processing the POMs: [ERROR] 'packaging' with value 'war' is invalid. Aggregator projects require 'pom' as packaging. @ line 9, column 16
    Pagehelper的 使用
    异步 json的使用
    分页技术 PageHelper
    Exception encountered during context initialization
  • 原文地址:https://www.cnblogs.com/lindaiyu/p/10994131.html
Copyright © 2011-2022 走看看