zoukankan      html  css  js  c++  java
  • SpringData_04_ JPA中的一对多

    1.JPA中的一对多

    在一对多关系中,我们习惯把一的一方称之为主表,把多的一方称之为从表。在数据库中建立一对多的关系,需要使用数据库的外键约束。

    什么是外键?

    指的是从表中有一列,取值参照主表的主键,这一列就是外键。

    2. 实体类关系建立以及映射配置

    在实体类中,由于客户是少的一方,它应该包含多个联系人,所以实体类要体现出客户中有多个联系人的信息,代码如下:

    一的一方Customer

    /**
     * 1.实体类和表的映射关系
     *      @Eitity
     *      @Table
     * 2.类中属性和表中字段的映射关系
     *      @Id
     *      @GeneratedValue
     *      @Column
     */
    @Entity
    @Table(name="cst_customer")
    public class Customer {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name="cust_id")
        private Long custId;
        @Column(name="cust_address")
        private String custAddress;
        @Column(name="cust_industry")
        private String custIndustry;
        @Column(name="cust_level")
        private String custLevel;
        @Column(name="cust_name")
        private String custName;
        @Column(name="cust_phone")
        private String custPhone;
        @Column(name="cust_source")
        private String custSource;
    
        //配置客户和联系人之间的关系(一对多关系)
        /**
         * 使用注解的形式配置多表关系
         *      1.声明关系
         *          @OneToMany : 配置一对多关系
         *              targetEntity :对方对象的字节码对象
         *      2.配置外键(中间表)
         *              @JoinColumn : 配置外键
         *                  name:外键字段名称
         *                  referencedColumnName:参照的主表的主键字段名称
         *
         *  * 在客户实体类上(一的一方)添加了外键了配置,所以对于客户而言,也具备了维护外键的作用
         *
         */
    
    //    @OneToMany(targetEntity = LinkMan.class)
    //    @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
        /**
         * 放弃外键维护权
         *      mappedBy:对方配置关系的属性名称
         * cascade : 配置级联(可以配置到设置多表的映射关系的注解上)
         *      CascadeType.all         : 所有
         *                  MERGE       :更新
         *                  PERSIST     :保存
         *                  REMOVE      :删除
         *
         * fetch : 配置关联对象的加载方式
         *          EAGER   :立即加载
         *          LAZY    :延迟加载
    
          */
        @OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
        private Set<LinkMan> linkMans = new HashSet<>();

     多的一方LinkMan

    @Entity
    @Table(name = "cst_linkman")
    public class LinkMan {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "lkm_id")
        private Long lkmId; //联系人编号(主键)
        @Column(name = "lkm_name")
        private String lkmName;//联系人姓名
        @Column(name = "lkm_gender")
        private String lkmGender;//联系人性别
        @Column(name = "lkm_phone")
        private String lkmPhone;//联系人办公电话
        @Column(name = "lkm_mobile")
        private String lkmMobile;//联系人手机
        @Column(name = "lkm_email")
        private String lkmEmail;//联系人邮箱
        @Column(name = "lkm_position")
        private String lkmPosition;//联系人职位
        @Column(name = "lkm_memo")
        private String lkmMemo;//联系人备注
    
        /**
         * 配置联系人到客户的多对一关系
         *     使用注解的形式配置多对一关系
         *      1.配置表关系
         *          @ManyToOne : 配置多对一关系
         *              targetEntity:对方的实体类字节码
         *      2.配置外键(中间表)
         *
         * * 配置外键的过程,配置到了多的一方,就会在多的一方维护外键
         *
         */
        @ManyToOne(targetEntity = Customer.class,fetch = FetchType.LAZY)
        @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
        private Customer customer;

    3.映射的注解说明

    @OneToMany:

         作用:建立一对多的关系映射

        属性:

                 targetEntityClass:指定多的多方的类的字节码

                 mappedBy:指定从表实体类中引用主表对象的名称。

                 cascade:指定要使用的级联操作

                 fetch:指定是否采用延迟加载

                 orphanRemoval:是否使用孤儿删除

    @ManyToOne

        作用:建立多对一的关系

        属性:

                 targetEntityClass:指定一的一方实体类字节码

                 cascade:指定要使用的级联操作

                 fetch:指定是否采用延迟加载

                 optional:关联是否可选。如果设置为false,则必须始终存在非空关系。

     

    @JoinColumn

         作用:用于定义主键字段和外键字段的对应关系。

         属性:

                 name:指定外键字段的名称

                 referencedColumnName:指定引用主表的主键字段名称

                 unique:是否唯一。默认值不唯一

                 nullable:是否允许为空。默认值允许。

                 insertable:是否允许插入。默认值允许。

                 updatable:是否允许更新。默认值允许。

                 columnDefinition:列的定义信息。

    4.JPA中的一对多测试

    RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class OneToManyTest {
    
        @Autowired
        private CustomerDao customerDao;
    
        @Autowired
        private LinkManDao linkManDao;
    
        /**
         * 保存一个客户,保存一个联系人
         *  效果:客户和联系人作为独立的数据保存到数据库中
         *      联系人的外键为空
         *  原因?
         *      实体类中没有配置关系
         */
        @Test
        @Transactional //配置事务
        @Rollback(false) //不自动回滚
        public void testAdd() {
            //创建一个客户,创建一个联系人
            Customer customer = new Customer();
            customer.setCustName("百度");
    
            LinkMan linkMan = new LinkMan();
            linkMan.setLkmName("小李");
    
            /**
             * 配置了客户到联系人的关系
             *      从客户的角度上:发送两条insert语句,发送一条更新语句更新数据库(更新外键)
             * 由于我们配置了客户到联系人的关系:客户可以对外键进行维护
             */
            customer.getLinkMans().add(linkMan);
    
    
            customerDao.save(customer);
            linkManDao.save(linkMan);
        }
    
    
        @Test
        @Transactional //配置事务
        @Rollback(false) //不自动回滚
        public void testAdd1() {
            //创建一个客户,创建一个联系人
            Customer customer = new Customer();
            customer.setCustName("百度");
    
            LinkMan linkMan = new LinkMan();
            linkMan.setLkmName("小李");
    
            /**
             * 配置联系人到客户的关系(多对一)
             *    只发送了两条insert语句
             * 由于配置了联系人到客户的映射关系(多对一)
             *
             *
             */
            linkMan.setCustomer(customer);
    
            customerDao.save(customer);
            linkManDao.save(linkMan);
        }
    
        /**
         * 会有一条多余的update语句
         *      * 由于一的一方可以维护外键:会发送update语句
         *      * 解决此问题:只需要在一的一方放弃维护权即可
         *
         */
        @Test
        @Transactional //配置事务
        @Rollback(false) //不自动回滚
        public void testAdd2() {
            //创建一个客户,创建一个联系人
            Customer customer = new Customer();
            customer.setCustName("百度");
    
            LinkMan linkMan = new LinkMan();
            linkMan.setLkmName("小李");
    
    
            linkMan.setCustomer(customer);//由于配置了多的一方到一的一方的关联关系(当保存的时候,就已经对外键赋值)
            customer.getLinkMans().add(linkMan);//由于配置了一的一方到多的一方的关联关系(发送一条update语句)
    
            customerDao.save(customer);
            linkManDao.save(linkMan);
        }
    }

    5.级联操作

    级联操作:指操作一个对象同时操作它的关联对象

    使用方法:只需要在操作主体的注解上配置cascade

    /**
         * cascade:配置级联操作
         *         CascadeType.MERGE    级联更新
         *         CascadeType.PERSIST    级联保存:
         *         CascadeType.REFRESH 级联刷新:
         *         CascadeType.REMOVE    级联删除:
         *         CascadeType.ALL        包含所有
         */
        @OneToMany(mappedBy="customer",cascade=CascadeType.ALL)

    6.级联添加和级联删除

    /**
         * 级联添加:保存一个客户的同时,保存客户的所有联系人
         *      需要在操作主体的实体类上,配置casacde属性
         */
        @Test
        @Transactional //配置事务
        @Rollback(false) //不自动回滚
        public void testCascadeAdd() {
            Customer customer = new Customer();
            customer.setCustName("百度1");
    
            LinkMan linkMan = new LinkMan();
            linkMan.setLkmName("小李1");
    
            linkMan.setCustomer(customer);
            customer.getLinkMans().add(linkMan);
    
            customerDao.save(customer);
        }
    
    
        /**
         * 级联删除:
         *      删除1号客户的同时,删除1号客户的所有联系人
         */
        @Test
        @Transactional //配置事务
        @Rollback(false) //不自动回滚
        public void testCascadeRemove() {
            //1.查询1号客户
            Customer customer = customerDao.findOne(1l);
            //2.删除1号客户
            customerDao.delete(customer);
        }

                                                                                                                                   ————你是我自罚三杯也不能开口的秘密

  • 相关阅读:
    Codeforces Round #719 (Div. 3) 题解
    Codeforces Global Round 14 A~F题解
    AtCoder Beginner Contest 199 题解
    Codeforces Round #716 (Div. 2) A~D 题解
    Codeforces Round #713 (Div. 3) 题解
    Codeforces Round #712 (Div. 2) A~E 题解
    CodeCraft-21 and Codeforces Round #711 (Div. 2) A~E 题解
    CF839 D 莫比乌斯反演
    java存大数和高精度浮点数(BigInteger与BigDecimal)
    java科学计算常用方法(Math)
  • 原文地址:https://www.cnblogs.com/asndxj/p/11815456.html
Copyright © 2011-2022 走看看