zoukankan      html  css  js  c++  java
  • Hibernate(6)关联关系_单向n对1

    1.单向 n-1 关联只需从 n 的一端可以访问 1 的一端

    2.实体类
    n端:Order.java

    public class Order {
        private Integer orderId;
        private String orderName;
        //在n端的实体类中有1端的类型的属性
        private Customer customer;
        //省略getter和setter方法
        ...
    }

    1端:Customer.java

    public class Customer {
    
        private Integer customerId;
        private String customerName;
        //省略getter和setter方法
        ...
    }

    3.映射文件
    n端:Order.hbm.xml

    <hibernate-mapping package="com.withXml.manyToone.entity">
        <class name="Order" table="ORDERS">
            <id name="orderId" type="java.lang.Integer">
                <column name="ORDER_ID" />
                <generator class="native" />
            </id>
            <property name="orderName" type="java.lang.String">
                <column name="ORDER_NAME" />
            </property>
    
        <!-- 在n的一端映射n对1关联关系 -->
        <many-to-one name="customer" class="Customer" column="CUSTOMER" cascade="save-update,delete"></many-to-one>
    
        </class>
    </hibernate-mapping>

    1:端Customer.hbm.xml

    <hibernate-mapping>
    
        <class name="com.withXml.manyToone.entity.Customer" table="CUSTOMERS">
    
            <id name="customerId" type="java.lang.Integer">
                <column name="CUSTOMER_ID" />
                <generator class="native" />
            </id>
    
            <property name="customerName" type="java.lang.String">
                <column name="CUSTOMER_NAME" />
            </property>
    
        </class>
    </hibernate-mapping>
    

    4.配置文件中添加Mapping元素

    <!-- 配置映射文件时,这两种方法只能使用其中之一,同时使用会报错 -->
        <!--使用配置文件时: 加载映射文件,注意使用的是斜杠作为分割符,有文件的后缀名 -->
        <!-- 使用注解时:加载持久化类文件,注意使用的是圆点作为分割符,无文件的后缀名 -->
    <mapping resource="com/withXml/manyToone/entity/Customer.hbm.xml"/>
    <mapping resource="com/withXml/manyToone/entity/Order.hbm.xml"/>

    5.CRUD测试

    public class TestManyToOne {
    
    
        //通常生产环境中不会定义Transaction对象 和Session对象为成员变量,因为会出现并发的问题,这是单元测试环境
        private SessionFactory sessionFactory;
        private Session session;
        private Transaction transaction;
    
        /**
         * 初始化Session
         */
        @Before
        public void init(){
            //1.获取Configuration 对象
            Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
            //2.获取ServiceRegistry 对象
            ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().
                        applySettings(configuration.getProperties()).
                        buildServiceRegistry();
            //3.获取SessionFactory 对象,并在ServiceRegistry 对象中注册
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            //4.获取Session 对象
            session = sessionFactory.openSession();
            //5.开启session事务
            transaction = session.beginTransaction();
        }
    
        /**
         * 关闭Session
         */
        @After
        public void destroy(){
            transaction.commit();
            session.close();
            sessionFactory.close();
        }
    
        /**
         * 执行保存操作时,先保存一的一端的对象,在保存多的一端的对象时,只有三条insert语句
         * 执行保存操作时,先保存多的一端的对象,在保存一的一端的对象时,有三条insert语句和两条update语句,
         *因为在插入多的一端无法确定外键值,所以只能等一的一端插入后,再更新
         */
        @Test
        public void testManyToOneSave(){
            //客户
            Customer customer = new Customer();
            customer.setCustomerName("CC");
            //订单一
            Order order = new Order();
            order.setOrderName("order-3");
            //订单二
            Order order2 = new Order();
            order2.setOrderName("order-4");
    
            //设定关联关系,从多的一端维护关联关系
            order.setCustomer(customer);
            order2.setCustomer(customer);
    
            //执行保存操作,先保存一的一端,在保存多的一端,推荐
            session.save(customer);
            session.save(order);
            session.save(order2);
    
            //先保存多的一端,在保存一的一端,不推荐
    //      session.save(order);
    //      session.save(order2);
    //      session.save(customer);
        }
    
        /**
         * 测试客户和订单之间的单向多对一的关联关系,查找操作
         * 若查询多的一端的一个对象,则默认情况下,只查询多的一端的对象,而没有查询关联的对象,即一的一端的对象
         *只有需要使用到关联的对象时,才发送相关的SQL语句,这就是Hibernate的懒加载机制
         * 若在加载关联的对象时,把session关了,就会出现懒加载异常
         */
        @Test
        public void testManyToOneGet(){
            Order order = (Order) session.get(Order.class, 1);
            System.out.println("订单名称:" + order.getOrderName());
            String name = order.getCustomer().getCustomerName();
            System.out.println("订单:" + order.getOrderName() + "的客户是:" + name);
    
        }
    
        /**
         * 测试修改操作
         */
        @Test
        public void testManyToOneUpdate(){
            Order order = (Order) session.get(Order.class, 1);
            order.getCustomer().setCustomerName("AAA");
        }
    
        /**
         * 测试删除操作,删除时,不能从关联的一端进行删除,因为在多的一端的外键引用了一的一端
         * 在多对一映射中,无法从1的一端删除,在一对多映射中,可以中1的一端删除记录,
         *同时还会强制把n端的外键也删除
         */
        @Test
        public void testManyToOneDelete(){
            //从一的一端,删除记录失败,因为一的一端外键被引用无法删除
    //      Customer customer = (Customer) session.get(Customer.class, 1);
    //      session.delete(customer);
            //从多的一端删除记录
            Order order = (Order) session.get(Order.class, 4);
            session.delete(order);
        }
    
        /**
         * 级联保存
         */
        @Test
        public void testManyToOneCascadeSave(){
            //客户
            Customer customer = new Customer();
            customer.setCustomerName("CC");
            //订单一
            Order order = new Order();
            order.setOrderName("order-3");
            //订单二
            Order order2 = new Order();
            order2.setOrderName("order-4");
    
            //设定关联关系,从多的一端维护关联关系
            order.setCustomer(customer);
            order2.setCustomer(customer);
    
            //执行保存操作,先保存一的一端,在保存多的一端,推荐,设置cascade级联属性之后,
            //仅只保存多端即可,从而省略1的一端,反之则不行因为没有一对多的的映射
    //      session.save(customer);
            session.save(order);
            session.save(order2);
    
        }
    
    }

    单向n对1
    总结:
    n端:
    ①实体类中添加一个1端类型的属性
    ②映射文件中使用<many-to-one 映射数据库字段

    1端:
    ①普通的javaBean
    ②映射文件,类属性和数据库字段一一映射即可

  • 相关阅读:
    mysql in 中使用子查询,会不使用索引而走全表扫描
    java集合之hashMap,初始长度,高并发死锁,java8 hashMap做的性能提升
    简要了解web安全之sql注入
    java之JVM学习--简单了解GC算法
    java之JVM学习--简单理解编译和运行的过程之概览
    java之JVM学习--基本机构
    JDK,JRE,JVM 关系和概念
    SpringAOP源码解析
    数据结构——实现list
    由数据库练习浅析子查询和链接查询
  • 原文地址:https://www.cnblogs.com/tengpengfei/p/10453958.html
Copyright © 2011-2022 走看看