• Hibernate多表的关联关系、懒加载


    参考文章:Hibernate实体关联关系映射,作者:骑猪下不来的猴

    一、什么是Hibernate中的关联映射?

    • 简单来说Hibernate是ORM映射的持久层框架,全称是(Object Relational Mapping),即对象关系映射。
    • 它将数据库中的表映射成对应的对象,以对象的形式展现,这样我们就可以通过映射的对象来对数据库中的数据进行间接的操作。
    • 关联映射是将数据库中的表映射成与之相对应的对象,当你对这个对象进行操作的时候,Hibernate会对数据库中对应的表执行相应的操作,你对该实体的操作实际上就是在间接的操作数据库中与之相对应的表。
    • Hibernate正是实现了这种思想,达到了方便开发人员以面向对象的思想来实现对数据库的操作。

    二、Hibernate的关联关系:

    1.单向关联:

    单向关联是指只有A方有B方的关联信息而B方没有A方的关联信息 。

    例如:
     	  A——>B
     	  A对象中有B对象的关联信息
     	  B对象中没有A对象的关联信息  
     	  我们可以通过A对象中B的关联信息查询或修改B对象的信息但无法通过B对象来查询修改A对象的信息
    
    • 1
    • 2
    • 3
    • 4
    • 5

    单向关联又分为:

    • 一对一单向关联
    • 一对多单项关联
    • 多对一单项关联
    • 多对多单项关联

    2.双向关联:

    例如:
     	  A<——>B
     	  A对象中有B对象的关联信息
     	  B对象中也有A对象的关联信息
     	  我们可以通过A对象中B的关联信息查询或修改B对象的信息也可以通过B对象中A的关联信息来查询修改A对象的信息
    
    • 1
    • 2
    • 3
    • 4
    • 5

    双向关联又分为:

    • 一对一双向关联
    • 一对多双向关联(多对一双向关联)
    • 多对多双向关联

    三、一对多与多对一关联:

    只在一方配置关联关系而另一方不进行配置。

    1.一对多单向关联:

    (1)思路:
    例如:
     	  Customer——>Order
          一个顾客(Customer)对应多个订单(Order)。
          当业务要求通过Customer可以获取该顾客下所有Order,但不能通过Order找到Customer时,这就需要一对多单向关联关系。
    
    • 1
    • 2
    • 3
    • 4

    一对多单向关联关系的实现是通过在Customer类中创建Order类的集合属性,这样我们能够通过Customer获取和修改该客户对应的Order集合。(但是不能通过Order获取和修改Customer)

    (2)代码实现:
    • 数据库表:

    order表中有外键指向customer表。
    在这里插入图片描述

    • 创建顾客实体类Customer,存储顾客信息:

    注意我们在顾客类中用S集合封装了顾客名下的订单信息。

    Customer类中要有订单Order的集合。

    import lombok.Getter;
    import lombok.Setter;
    import java.util.Set;
    @Getter
    @Setter
    public class Customer {
        private int id;
        private String name;
        private Integer age;
        //在顾客表中加入订单集合
        private Set<Order> orders;
    
        @Override
        public String toString() {
            return "Customer{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    ", orders=" + orders +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • Order类:
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Order {
        private int id;
        private String orderNumber;
        private Double orderPrice;
    	//注意这里没有定义数据库中的外键属性
        @Override
        public String toString() {
            return "Order{" +
                    "id=" + id +
                    ", orderNumber='" + orderNumber + '\'' +
                    ", orderPrice=" + orderPrice +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • Customer.hbm.xml:
    <hibernate-mapping package="org.example.Entity">
        <class name="Customer" table="customer">
            <id name="id" column="id" type="java.lang.Integer"/>
            <property name="name" column="name" type="java.lang.String"/>
            <property name="age" column="age" type="java.lang.Integer"/>
            
            <set name="orders" table="`order`">
                
                <key column="customer_id"/>
                
                <one-to-many class="org.example.Entity.Order"/>
            set>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • Order.hbm.xml:
    <hibernate-mapping>
        <class name="org.example.Entity.Order" table="`order`">
            <id name="id" column="id" type="java.lang.Integer"/>
            <property name="orderNumber" column="orderNumber" type="java.lang.String"/>
            <property name="orderPrice" column="orderPrice" type="java.lang.Double"/>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 测试类及运行结果:
    @Test
    public void test3(){
        //创建SessionFactory,从根路径下获取核心配置文件
        SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        //创建session
        Session session = factory.openSession();
        //创建并开启事务
        Transaction transaction = session.beginTransaction();
        //获取Customer主键为1的顾客信息及其所有订单信息
        Customer customer = session.get(Customer.class,1);
        //打印数据
        System.out.println(customer.toString());
        //提交事务
        transaction.commit();
        //关闭SessionFactory
        factory.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    2.多对一单向关联:

    (1)思路:
    例如:
     	  Customer<——Order
          多个订单(Order)属于一个顾客(Customer)。
          当业务要求通过Order可以获取该订单所属Customer,但不能通过Customer找到Order时,这就需要多对一单向关联关系。
    
    • 1
    • 2
    • 3
    • 4

    多对一单向关联关系的实现是通过在Order类中创建Customer类作为属性,这样我们能够通过Order获取和修改该客户Customer的信息。(但是不能通过Customer获取和修改Order)

    (2)代码实现:
    • 数据库表:

    order表中有外键指向customer表。
    在这里插入图片描述

    • Customer类:
    package org.example.Entity;
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Customer {
        private int id;
        private String name;
        private Integer age;
    
        @Override
        public String toString() {
            return "Customer{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 创建订单类Order,存储订单信息:

    订单类中应该有顾客类,用来指明该订单属于哪个顾客。
    订单类中要有顾客属性,类型是顾客类的类型。

    package org.example.Entity;
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Order {
        private int id;
        private String orderNumber;
        private Double orderPrice;
        //订单类中要有顾客Customer属性
        private Customer customer;
    
        @Override
        public String toString() {
            return "Order{" +
                    "id=" + id +
                    ", orderNumber='" + orderNumber + '\'' +
                    ", orderPrice=" + orderPrice +
                    ", customer=" + customer +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • Customer.hbm.xml:
    <hibernate-mapping package="org.example.Entity">
        <class name="Customer" table="customer">
            <id name="id" column="id" type="java.lang.Integer"/>
            <property name="name" column="name" type="java.lang.String"/>
            <property name="age" column="age" type="java.lang.Integer"/>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • Order.hbm.xml:
    <hibernate-mapping>
        <class name="org.example.Entity.Order" table="`order`">
            <id name="id" column="id" type="java.lang.Integer"/>
            <property name="orderNumber" column="orderNumber" type="java.lang.String"/>
            <property name="orderPrice" column="orderPrice" type="java.lang.Double"/>
            
            <many-to-one name="customer" column="customer_id"  class="org.example.Entity.Customer"/>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 测试类及运行结果:
    @Test
    public void test3(){
        //创建SessionFactory,从根路径下获取核心配置文件
        SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        //创建session
        Session session = factory.openSession();
        //创建并开启事务
        Transaction transaction = session.beginTransaction();
        //获取订单主键为111的订单信息及该订单所属的顾客信息
        Order order = session.get(Order.class,111);
        //打印数据
        System.out.println(order.toString());
        //提交事务
        transaction.commit();
        //关闭SessionFactory
        factory.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    3.一对多(多对一)双向关联:

    (1)思路:
    例如:
     	  Customer<——>Order
          一个顾客(Customer)对应多个订单(Order)。
          当业务要求通过Customer可以获取该顾客下所有Order,且通过Order能获取对应Customer时,这就需要一对多双向关联关系。
    
    • 1
    • 2
    • 3
    • 4

    双向关联关系就是同时使用一对多单向关联和多对一单向关联。 所以需要在Customer类中创建Order类的集合属性,并在Order类中创建Customer属性。

    双向关联时易错点inverse属性:

    我们进行双向关联后,顾客类中有订单类,订单类中有顾客类,当我们想要执行插入操作时,如果双方都维护关联关系,那么会出现重复执行SQL语句的情况,使得效率低下。
    所以我们需要配置一个属性,让双向关联的某一方交出维护权。
    inverse=“true” 表示将关联关系交由对方控制。inverse=“false” 表示自己控制关联关系。

    补充cascade属性:

    该属性表示级联操作,cascade=“delete” 设置级联删除,设置后当删除某一行时,会级联删除绑定该行外键的其他行。

    (2)代码实现:
    • 数据库表:

    order表中有外键指向customer表。
    在这里插入图片描述

    • 创建顾客实体类Customer,存储顾客信息:

    注意我们在顾客类中用S集合封装了顾客名下的订单信息。

    Customer类中要有订单Order的集合。

    import lombok.Getter;
    import lombok.Setter;
    import java.util.Set;
    @Getter
    @Setter
    public class Customer {
        private int id;
        private String name;
        private Integer age;
        //在顾客表中加入订单集合
        private Set<Order> orders;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 创建订单类Order,存储订单信息:

    订单类中应该有顾客类,用来指明该订单属于哪个顾客。
    订单类中要有顾客属性,类型是顾客类的类型。

    package org.example.Entity;
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Order {
        private int id;
        private String orderNumber;
        private Double orderPrice;
        //订单类中要有顾客Customer属性
        private Customer customer;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • Customer.hbm.xml:
    <hibernate-mapping package="org.example.Entity">
        <class name="Customer" table="customer">
            <id name="id" column="id" type="java.lang.Integer"/>
            <property name="name" column="name" type="java.lang.String"/>
            <property name="age" column="age" type="java.lang.Integer"/>
            
            
            <set name="orders" table="`order`" inverse="true" cascade="delete">
                
                <key column="customer_id"/>
                
                <one-to-many class="org.example.Entity.Order"/>
            set>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • Order.hbm.xml:
    <hibernate-mapping>
        <class name="org.example.Entity.Order" table="`order`">
            <id name="id" column="id" type="java.lang.Integer"/>
            <property name="orderNumber" column="orderNumber" type="java.lang.String"/>
            <property name="orderPrice" column="orderPrice" type="java.lang.Double"/>
            
            <many-to-one name="customer" column="customer_id"  class="org.example.Entity.Customer"/>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 测试类及运行结果:
    @Test
    public void test3(){
        //创建SessionFactory,从根路径下获取核心配置文件
        SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        //创建session
        Session session = factory.openSession();
        //创建并开启事务
        Transaction transaction = session.beginTransaction();
        //获取订单主键为111的订单信息及该订单所属的顾客信息
        Order order = session.get(Order.class,111);
        //打印数据
        System.out.println(order.getCustomer().getName());
        //提交事务
        transaction.commit();
        //关闭SessionFactory
        factory.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    (3)关联插入操作的实现:

    • 测试类:
      注意要建立关联关系。
    public class AppTest{
        @Test
        public void test(){
            //创建SessionFactory,从根路径下获取核心配置文件
            SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
            //创建session
            Session session = factory.openSession();
            //创建事务
            Transaction transaction = session.beginTransaction();
            //创建顾客类对象并给相应属性赋值
            CustomerEntity customer = new CustomerEntity();
            customer.setId(4);
            customer.setName("44");
            customer.setAge(18);
            //创建订单类对象并给相应属性赋值
            OrdersEntity order = new OrdersEntity();
            order.setId(4);
            order.setOrderNumber("4");
            order.setOrderPrice(4.0);
            //建立关联关系,若不建立关联关系order表的数据为空
            order.setCustomer(customer);
            //保存,所有对象都要保存
            session.save(customer);
            session.save(order);
            //提交事务
            transaction.commit();
            //关闭SessionFactory
            factory.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 运行结果:
      在这里插入图片描述

    四、多对多关联:

    1.多对多单向关联:

    (1)思路:

    例如:
     	  Pupil===>Course
          一个学生(Pupil)有多门课程(Course)。
          当业务要求通过Pupil学生可以获取该学生的所有课程Course,但通过Course课程不能获取对应Pupil学生时,这就需要多对多单向关联关系。
    
    • 1
    • 2
    • 3
    • 4

    多对多关系通过一个中间表来维护。
    在这里插入图片描述

    (2)代码实现:

    • 数据库表:

    pupil_course表中有两个外键分别指向pupil表和course表的主键。
    在这里插入图片描述

    • 创建Pupil实体类:

    Pupil类中有课程Course的集合。

    import lombok.Getter;
    import lombok.Setter;
    import java.util.Set;
    
    @Getter
    @Setter
    public class Pupil {
        private int aid;
        private String aname;
        private Set<Course> courses;
    
        @Override
        public String toString() {
            return "Pupil{" +
                    "aid=" + aid +
                    ", aname='" + aname + '\'' +
                    ", courses=" + courses +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 创建Course实体类:
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Course {
        private int cid;
        private String cname;
    
        @Override
        public String toString() {
            return "Course{" +
                    "cid=" + cid +
                    ", cname='" + cname + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 创建中间表实体类:
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class PupilCourse {
        private int id;
        private Integer aid;
        private Integer cid;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 创建Pupil实体类映射文件:
    <hibernate-mapping>
        <class name="org.example.Entity.Pupil" table="pupil">
            <id name="aid" column="aid" type="java.lang.Integer"/>
            <property name="aname" column="aname" type="java.lang.String"/>
            <set name="courses" table="pupil_course" >
                <key column="aid"/>
                
                <many-to-many class="org.example.Entity.Course" column="cid"/>
            set>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 创建Course实体类映射文件:
    <hibernate-mapping>
        <class name="org.example.Entity.Course" table="course">
            <id name="cid" column="cid" type="java.lang.Integer"/>
            <property name="cname" column="cname" type="java.lang.String"/>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 创建中间表实体类映射文件:
    <hibernate-mapping>
        <class name="org.example.Entity.PupilCourse" table="pupil_course">
            <id name="id" column="id" type="java.lang.Integer"/>
            <property name="aid" column="aid" type="java.lang.Integer"/>
            <property name="cid" column="cid" type="java.lang.Integer"/>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 测试类及运行结果:
    @Test
    public void test8(){
        //创建SessionFactory,从根路径下获取核心配置文件
        SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        //创建session
        Session session = factory.openSession();
        //创建事务
        Transaction transaction = session.beginTransaction();
        //获取主键ID为0的学生信息及其选课信息
        Pupil pupil = session.get(Pupil.class,0);
        //输出结果
        System.out.println(pupil.toString());
        //提交事务
        transaction.commit();
        //关闭SessionFactory
        factory.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    2.多对多双向关联:

    (1)思路:

    例如:
     	  Pupil<===>Course
          一个学生(Pupil)有多门课程(Course),一门课程有多个学生选择。
          当业务要求通过Pupil学生可以获取该学生的所有课程Course,且通过Course课程能获取对应Pupil学生时,这就需要多对多双向关联关系。
    
    • 1
    • 2
    • 3
    • 4

    多对多关系通过一个中间表来维护。
    在这里插入图片描述

    易错:双向关联关系注意设置inverse和cascade属性。

    (2)代码实现:

    • 数据库表:

    pupil_course表中有两个外键分别指向pupil表和course表的主键。
    在这里插入图片描述

    • 创建Pupil实体类:

    Pupil类中有课程Course的集合。

    import lombok.Getter;
    import lombok.Setter;
    import java.util.Set;
    
    @Getter
    @Setter
    public class Pupil {
        private int aid;
        private String aname;
        private Set<Course> courses;
    
        @Override
        public String toString() {
            return "Pupil{" +
                    "aid=" + aid +
                    ", aname='" + aname + '\'' +
                    ", courses=" + courses +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 创建Course实体类:

    Course类中有课程Pupil的集合。

    import lombok.Getter;
    import lombok.Setter;
    
    import java.util.Set;
    
    @Getter
    @Setter
    public class Course {
        private int cid;
        private String cname;
        private Set<Pupil> pupils;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 创建中间表实体类:
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class PupilCourse {
        private int id;
        private Integer aid;
        private Integer cid;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 创建Pupil实体类映射文件:
    <hibernate-mapping>
        <class name="org.example.Entity.Pupil" table="pupil">
            <id name="aid" column="aid" type="java.lang.Integer"/>
            <property name="aname" column="aname" type="java.lang.String"/>
            <set name="courses" table="pupil_course">
                <key column="aid"/>
                
                <many-to-many class="org.example.Entity.Course" column="cid"/>
            set>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 创建Course实体类映射文件:
    <hibernate-mapping>
        <class name="org.example.Entity.Course" table="course">
            <id name="cid" column="cid" type="java.lang.Integer"/>
            <property name="cname" column="cname" type="java.lang.String"/>
            <set name="pupils" table="pupil_course">
                <key column="cid">key>
                <many-to-many class="org.example.Entity.Pupil" column="aid">many-to-many>
            set>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 创建中间表实体类映射文件:
    <hibernate-mapping>
        <class name="org.example.Entity.PupilCourse" table="pupil_course">
            <id name="id" column="id" type="java.lang.Integer"/>
            <property name="aid" column="aid" type="java.lang.Integer"/>
            <property name="cid" column="cid" type="java.lang.Integer"/>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 测试类及运行结果:
    @Test
    public void test8(){
        //创建SessionFactory,从根路径下获取核心配置文件
        SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        //创建session
        Session session = factory.openSession();
        //创建事务
        Transaction transaction = session.beginTransaction();
        //获取主键ID为0的课程信息及课程内的学生
        Course course = session.get(Course.class,0);
        //输出结果
        for (Pupil pupil : course.getPupils()) {
            System.out.println(pupil.getAname());
        }
        //提交事务
        transaction.commit();
        //关闭SessionFactory
        factory.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    (3)关联插入操作的实现:

    • 测试类:
        @Test
        public void test2(){
            //创建SessionFactory,从根路径下获取核心配置文件
            SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
            //创建session
            Session session = factory.openSession();
            //创建事务
            Transaction transaction = session.beginTransaction();
            //创建Courses类对象并给相应属性赋值
            CoursesEntity course = new CoursesEntity();
            course.setCname("JAVA");
            //创建Accounts类对象并给相应属性赋值
            AccountsEntity account = new AccountsEntity();
            account.setAname("张三");
            //建立关联关系
            Set<CoursesEntity> courses = new HashSet<>();
            courses.add(course);
            account.setCourses(courses);
            //保存,所有对象都要保存
            session.save(course);
            session.save(account);
            //提交事务
            transaction.commit();
            //关闭SessionFactory
            factory.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 运行结果:
      在这里插入图片描述

    五、一对一关联:

    一对一单向关联没有测出来,所以没写,有会实现的的欢迎与我交流。

    1.一对一双向关联:

    (1)思路:
    例如:
     	  Person<——>Address
          一个人(Person)对应一个家(Address)。
          当业务要求通过Person可以获取他的家庭住址Address,且能通过Address找到Person时,这就需要一对一双向关联关系。
    
    • 1
    • 2
    • 3
    • 4

    一对一双向关联关系的实现是通过在Person类中创建Address类作为属性,并在Address类中创建Person类作为属性

    (2)代码实现:
    • 数据库表:

    在这里插入图片描述

    • Person类:

    Person类中要有地址Address类作为属性。

    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Person {
        private int personId;
        private String personName;
        private String personPhone;
        //Person类中要有地址Address类
        private Address address;
    
        @Override
        public String toString() {
            return "Person{" +
                    "personId=" + personId +
                    ", personName='" + personName + '\'' +
                    ", personPhone='" + personPhone + '\'' +
                    ", address=" + address +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • Address类:

    Address类中要有Person类作为属性。

    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Address {
        private int addressId;
        private String addressDetail;
        //Address类中要有地址Person类
        private Person person;
    
        @Override
        public String toString() {
            return "Address{" +
                    "addressId=" + addressId +
                    ", addressDetail='" + addressDetail + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • Person.hbm.xml:
    <hibernate-mapping>
        <class name="org.example.Entity1.Person" table="person">
            <id name="personId" column="person_id"/>
            <property name="personName" column="person_name"/>
            <property name="personPhone" column="person_phone"/>
            
            <one-to-one name="address"  class="org.example.Entity1.Address" property-ref="person" />
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • Address.hbm.xml:
    <hibernate-mapping>
        <class name="org.example.Entity1.Address" table="address">
            <id name="addressId" column="address_id"/>
            <property name="addressDetail" column="address_detail"/>
            
            <many-to-one name="person" column="personid" unique="true" class="org.example.Entity1.Person"/>
        class>
    hibernate-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 测试类及运行结果:
        @Test
        public void test1(){
            //创建SessionFactory,从根路径下获取核心配置文件
            SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
            //创建session
            Session session = factory.openSession();
            //创建事务
            Transaction transaction = session.beginTransaction();
            //创建实体类对象并给相应属性赋值
            Person person = session.get(Person.class,1);
            System.out.println(person);
            //提交事务
            transaction.commit();
            //关闭SessionFactory
            factory.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    六、懒加载:

    懒加载条件下查询顾客信息和订单信息。

    什么是懒加载?点击查看

    具体配置同上。
    需要在customer类的映射文件中为order的set集合配置 lazy="true",设置order的懒加载,这样在查询customer信息时会根据需求判断是否查询order。
    需要在order类的映射文件中为customer的many-to-one设置lazy=proxy",设置customer的懒加载,这样在查询order信息时会根据需求判断是否查询customer。
    默认条件下所有Hibernate映射文件都会开启懒加载。

    • 测试类1:
    @Test
    public void test3(){
        //创建SessionFactory,从根路径下获取核心配置文件
        SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        //创建session
        Session session = factory.openSession();
        //创建事务
        Transaction transaction = session.beginTransaction();
        //查询主键为4的顾客信息
        CustomerEntity customer = session.get(CustomerEntity.class,4);
        System.out.println(customer);
        //提交事务
        transaction.commit();
        //关闭SessionFactory
        factory.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 运行结果1:

    因为会调用toString方法,toString会打印学生信息和订单信息,所以有两条SQL语句。
    在这里插入图片描述
    如果只打印customer.name(),则只会有第一条SQL,这就是懒加载。

    • 测试类2:
    @Test
    public void test4(){
        //创建SessionFactory,从根路径下获取核心配置文件
        SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
        //创建session
        Session session = factory.openSession();
        //创建事务
        Transaction transaction = session.beginTransaction();
        //查询主键为4的订单信息
        OrdersEntity orders = session.get(OrdersEntity.class,4);
        System.out.println(orders);
        //提交事务
        transaction.commit();
        //关闭SessionFactory
        factory.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 运行结果2:
      在这里插入图片描述
      如果只打印order.name(),则只会有第一条SQL,这就是懒加载。
  • 相关阅读:
    【lc刷题 day2】树的子结构 二叉树的镜像 对称的二叉树 顺时针打印矩阵
    C的魅力在于指针
    Java——聊聊JUC中的Java内存模型(JMM)
    5G NR preamble生成原理
    基于微服务、Java、Springcloud、Vue、MySQL开发的智慧工地管理系统源码
    华为eNSP配置专题-浮动路由及BFD的配置
    python实现命令tree的效果
    小程序DevTools-main抓包
    Elasticsearch 分片内部原理—近实时搜索、持久化变更
    Google PLB(Protective Load Balancing) 简评
  • 原文地址:https://blog.csdn.net/m0_53881899/article/details/127972209