双向一对一

Posted shiningarmor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双向一对一相关的知识,希望对你有一定的参考价值。

@OneToOne注解用来一对一映射;
需要在被维护关系的一端加上属性 mappedBy 来表示放弃维护关联关系;
 
例如:可以建立两个类 Company、Boss;
假设一个公司只有一个老板,而一个老板只有一个公司;只是这么假设;
 
Boss类:
维护关联关系的一端需要用@JoinColumn注解的name 属性来指定外键名;
注意:由于是一对一映射,需要加上unique=true属性;
     @JoinColumn(name="b_id",unique=true)
     @OneToOne
     private Boss boss;
 
Company类:
不维护关联关系的一端要在@OneToOne里面添加mappedBy属性来指定用另一个类的哪个属性来映射关联关系;
也就是说mappedBy的值是另一个类中外键类属性的属性名;例如Boss类中的 private Company company;
有了mappedBy就不能用@JoinColumn;
     @OneToOne(mappedBy="boss")
     private Company company;
 
1.插入
     //测试一对一添加
     @Test
     public void testInsert(){
           Boss boss=new Boss();
           boss.setBname("曹操老板");
           
           Company company=new Company();
           company.setCname("曹魏集团");
           
           boss.setCompany(company);
           company.setBoss(boss);
           
           manager.persist(company);
           manager.persist(boss);
     }
结果:
Hibernate:
    insert
    into
        tb_comp
        (b_id, cname)
    values
        (?, ?)
Hibernate:
    insert
    into
        tb_boss
        (bname)
    values
        (?)
Hibernate:
    update
        tb_comp
    set
        b_id=?,
        cname=?
    where
        cid=?
插入成功后,维护关联关系的company对应的表中会多出一列外键;
如果是先插入维护关联关系的一方,则会有一条update语句;
如果是先插入不维护关联关系的一方,这里是boss,将不会有update语句;
 
在插入时建议先插入没有外键的一方;
 
2.查询
1)如果查询维护关联关系的一端
     //测试一对一查找
     @Test
     public void testFind(){
           Company comp=manager.find(Company.class, 1);
           
     }
结果:
Hibernate:
    select
        company0_.cid as cid1_1_1_,
        company0_.b_id as b_id3_1_1_,
        company0_.cname as cname2_1_1_,
        boss1_.bid as bid1_0_0_,
        boss1_.bname as bname2_0_0_
    from
        tb_comp company0_
    left outer join
        tb_boss boss1_
            on company0_.b_id=boss1_.bid
    where
        company0_.cid=?
Hibernate:
    select
        company0_.cid as cid1_1_1_,
        company0_.b_id as b_id3_1_1_,
        company0_.cname as cname2_1_1_,
        boss1_.bid as bid1_0_0_,
        boss1_.bname as bname2_0_0_
    from
        tb_comp company0_
    left outer join
        tb_boss boss1_
            on company0_.b_id=boss1_.bid
    where
        company0_.b_id=?
 
默认会通过左外链接来查询;并且发出两条查询语句;
可以通过在@OneToOne注解后面加上 fetch属性,改为懒加载;会只有一条查询语句;
     @JoinColumn(name="b_id",unique=true)
     @OneToOne(fetch=FetchType.LAZY)
     private Boss boss;
改为懒加载后的结果:
Hibernate:
    select
        company0_.cid as cid1_1_0_,
        company0_.b_id as b_id3_1_0_,
        company0_.cname as cname2_1_0_
    from
        tb_comp company0_
    where
        company0_.cid=?
 
2)查询不维护关联关系的一端
     //查询不维护关联关系的一端
     @Test
     public void testFind2(){
           Boss boss=manager.find(Boss.class, 1);
     }
结果:
Hibernate:
    select
        boss0_.bid as bid1_0_1_,
        boss0_.bname as bname2_0_1_,
        company1_.cid as cid1_1_0_,
        company1_.b_id as b_id3_1_0_,
        company1_.cname as cname2_1_0_
    from
        tb_boss boss0_
    left outer join
        tb_comp company1_
            on boss0_.bid=company1_.b_id
    where
        boss0_.bid=?
会发出一条左外连接查询;
如果改为修改 fetch为懒加载 会发出两条查询语句;
 
因为Boss类对应的表中没有外键;
因此不可能生成通过外键id生成代理对象;
只能发出两条sql或进行左外连接查询否则无法处理关联的对象的信息 ;
通常不维持关联关系的一端不建议用懒加载;
 
 

以上是关于双向一对一的主要内容,如果未能解决你的问题,请参考以下文章

原则 2:如何更新一对一的双向

JPA双向一对多多一对一

双向一对一

hibernate中配置单向多对一关联,和双向一对多

如何在外键上进行双向一对一关联[重复]

java之hibernate之基于外键的双向一对一关联映射