zoukankan      html  css  js  c++  java
  • 9、JPA_映射双向一对一的关联关系

    双向一对一的关联关系

    举例说明:经理Manager和部门Department是双向一对一关联关系。则Manager实体类中有Department实体对象的引用,反之亦然。

    其实体属性定义如下:

    List_1. Manager实体类属性定义(有对Department实体对象的引用)
     1 @Table(name="t_manager")
     2 @Entity
     3 public class Manager {
     4     
     5     private Integer id;
     6     private String mgrName;
     7     
     8     //有对实体Department对象的引用
     9     private Department dept;
    10 
    11     //省略getter、setter方法...
    12 }
    List_2. Department实体类属性定义(有对Manager实体对象的引用)
     1 @Table(name="t_department")
     2 @Entity
     3 public class Department {
     4     
     5     private Integer id;
     6     private String deptName;
     7     
     8     //有对Manager实体对象的引用
     9     private Manager mgr;
    10 
    11     //省略getter、setter方法...
    12 
    13 }

    双向一对一的关联关系映射方法有两种:基于外键的映射、基于主键的映射。

    这里讲使用较多的基于外键的映射。其映射步骤如下(例子中假定由Manager一方维护关联关系,Department一方放弃维护关联关系):

    1、双方都使用使用@OneToOne注解来映射关联关系;

    2、只需要一方维护关联关系(任何一方都可以):

         ①、放弃维护关联关系的一方需要配置@OneToOne的mappedBy属性,用于指定由对方的哪个属性来映射,同时不能使用@JoinColum注解(和前面讲的双向一对多关联关系是一样的)。放弃维护关联关系的一方所对应的数据表没有外键列。如下Department实体中的映射注解:

    List_3. Department实体类的映射注解(放弃维护关联关系,指定由对方的dept属性来进行关联;不能使用@JoinColumn注解)
    @OneToOne(mappedBy="dept")
    public Manager getMgr() {
        return mgr;
    }

         ②、维护关联的一方需要使用@JoinColumn注解来指定外键列的列名,同时还要指定外键列的唯一约束:@JoinColumn(name="DEPT_ID", unique=true)。维护关联关系的一方实体对应的数据表有一个外键列,列名由name属性指定。如下Manager实体类中的映射注解:

    List_4. Manager实体类的映射注解(由@JoinColumn注解的name属性指定表的外键列的列名,同时指定外键列的唯一约束)
    @JoinColumn(name="DEPT_ID", unique=true)
    @OneToOnepublic Department getDept() {
        return dept;
    }

    再讲一下映射的默认属性,同上面一样由Manager一方维护关联关系:

    1、默认情况下,双方对实体类对象的引用均采用立即加载的检索策略,这是符合前面 8、双向一对多关联关系 一节所阐述的“默认情况下,对象属性采用立即检索,集合属性采用延迟检索”。

    2、修改默认检索策略:

         ①、维护关联关系的一方(如Manager)所对应的数据表有外键列,可以通过设置@OneToOne的属性fetch=FetchType.LAZY来设置延迟加载策略。

         ②、放弃维护关联关系的一方(如Department)所对应的数据表中没有外键,即便设置了fetch=FetchType.LAZY也不能够达到延迟加载的效果。相反,如果设置了fetch=FetchType.LAZY以后还会多发送一条sql语句(两条select语句);没有设置的时候,只发送一条sql语句(一条带left outer join的select语句)。

    3、保存顺序,先保存放弃维护关联关系的一方实体,后保存维护关联关系的一方实体。这样可以避免发送update语句。

    下面是实验代码清单:

    List_5. Department实体(放弃维护关联关系,指定由对方的dept属性来进行关联;不能使用@JoinColumn注解)

     1 package com.magicode.jpa.doubl.one2one;
     2 
     3 import javax.persistence.Column;
     4 import javax.persistence.Entity;
     5 import javax.persistence.GeneratedValue;
     6 import javax.persistence.Id;
     7 import javax.persistence.OneToOne;
     8 import javax.persistence.Table;
     9 
    10 @Table(name="t_department")
    11 @Entity
    12 public class Department {
    13     
    14     private Integer id;
    15     private String deptName;
    16     
    17     private Manager mgr;
    18 
    19     @Column(name="ID")
    20     @GeneratedValue
    21     @Id
    22     public Integer getId() {
    23         return id;
    24     }
    25 
    26     @Column(name="DEPT_NAME", length=25)
    27     public String getDeptName() {
    28         return deptName;
    29     }
    30 
    31     /**
    32      * 通过mapptedBy指定由关联对象的那个属性建立起连接 
    33      * Manger实体对应的数据表没有外键,无法使用延迟加载策略
    34      * 所以使用默认的检索方式就好。
    35      * 如果设置了fetch=FetchType.LAZY反而会多发送一条sql语句。
    36      */
    37     @OneToOne(mappedBy="dept")
    38     public Manager getMgr() {
    39         return mgr;
    40     }
    41 
    42     @SuppressWarnings("unused")
    43     private void setId(Integer id) {
    44         this.id = id;
    45     }
    46 
    47     public void setDeptName(String deptName) {
    48         this.deptName = deptName;
    49     }
    50 
    51     public void setMgr(Manager mgr) {
    52         this.mgr = mgr;
    53     }
    54 }

    List_6. Manager实体(由@JoinColumn注解的name属性指定表的外键列的列名,同时指定外键列的唯一约束)

    package com.magicode.jpa.doubl.one2one;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.OneToOne;
    import javax.persistence.Table;
    
    @Table(name="t_manager")
    @Entity
    public class Manager {
        
        private Integer id;
        private String mgrName;
        
        private Department dept;
    
        @Column(name="ID")
        @GeneratedValue
        @Id
        public Integer getId() {
            return id;
        }
    
        @Column(name="MGR_NAME", length=25)
        public String getMgrName() {
            return mgrName;
        }
    
        /**
         * 默认情况下对Department属性的检索采用立即检索策略。
         * 由于Manager实体对应的数据表有外键列,所以可以设置
         * fetch=FetchType.LAZY来修改为延迟加载策略。
         * 
         * 注意:对没有外键类的一方(Department一方)则无法实现
         * 延迟加载策略。设置 fetch=FetchType.LAZY以后反而会
         * 多发送一条sql语句。
         */
        @JoinColumn(name="DEPT_ID", unique=true)
        @OneToOne(fetch=FetchType.LAZY)
        public Department getDept() {
            return dept;
        }
    
        @SuppressWarnings("unused")
        private void setId(Integer id) {
            this.id = id;
        }
    
        public void setMgrName(String mgrName) {
            this.mgrName = mgrName;
        }
    
        public void setDept(Department dept) {
            this.dept = dept;
        }
    
    }

    List_7. 测试代码:

    package com.magicode.jpa.doubl.one2one;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Persistence;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    public class DoubleOne2OneTest {
        
        private EntityManagerFactory emf = null;
        private EntityManager em = null;
        private EntityTransaction transaction = null;
        
        @Before
        public void before(){
            emf = Persistence.createEntityManagerFactory("jpa-1");
            em = emf.createEntityManager();
            transaction = em.getTransaction();
            transaction.begin();
        }
        
        @After
        public void after(){
            transaction.commit();
            em.close();
            emf.close();
        }
        
        @Test
        public void testPersist(){
            Department dept = new Department();
            dept.setDeptName("Dept-AA");
            
            Manager mgr = new Manager();
            mgr.setMgrName("Mgr-AA");
            
            //创建关联关系
            dept.setMgr(mgr);
            mgr.setDept(dept);
            
            /**
             * 持久化的时候,先持久化没有外键的那个对象,在持久化有
             * 外间的对象。这样就会避免发送update语句。
             */
            em.persist(dept);
            em.persist(mgr);
        }
        
        @Test
        public void testFind(){
            /**
             * 默认情况下,双向1-1关联关系中,在检索的时候都采用立即
             * 检索的策略(通过左外连接的方式查找与其相关联的属性)。
             * 
             * 有外键的那一方实体可以通过设置@OneToOne注解的fetch=FetchType.LAZY来
             * 修改默认检索策略。将其设置为延迟加载(对实体对象索引的检索)。
             * 
             * 对于没有外键的那一方而言,我们不需要修改其默认的检索方式。因为,无论你是否设置
             * fetch=FetchType.LAZY都会立即加载其关联的那一方实体(其没有对应的外键列,
             * 如果在检索的时候不加载,以后就无法找到其关联的实体对象了)。
             * 而且,如果设置了fetch=FetchType.LAZY还会稍微的有一点儿影响性能:默认情况下
             * 采用左外连接的方式,只会发送一条sql语句;而如果设置了fetch=FetchType.LAZY
             * 则会发送两条sql语句。
             */
    //        Manager mgr = em.find(Manager.class, 2);
    //        System.out.println(mgr.getMgrName());
    //        System.out.println(mgr.getDept().getClass().getName());
    //        
    //        System.out.println("--------------->");
            
            Department dept = em.find(Department.class, 3);
    //        System.out.println(dept.getDeptName());
    //        System.out.println(dept.getMgr().getClass().getName());
            
            
        }
    
    }
  • 相关阅读:
    环境是如何建立的 启动文件有什么
    环境中存储的是什么
    串行 并行 异步 同步
    TPC-H is a Decision Support Benchmark
    进程通信类型 管道是Linux支持的最初Unix IPC形式之一 命名管道 匿名管道
    删除环境变量
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
  • 原文地址:https://www.cnblogs.com/lj95801/p/5011137.html
Copyright © 2011-2022 走看看