zoukankan      html  css  js  c++  java
  • hibernate 双向 OneToOne fetchType lazy 问题

     

    hibernate 双向 OneToOne fetchType lazy 问题

    分类: hibernate

    转载于:http://mshijie.javaeye.com/admin/blogs/440057

    今天使用JPA(Hibernate)实现一个一对一关联的时候,发现无法使用延迟加载.Person关联一个Picture.在读取Person的时候,显示的记载了对于的Picture.读取10个Person发生了11次数据库查询.

    最后查阅资料后,发现是自己对OneToOne理解不够透彻所致.之前的关联是这么定义的.

    Person 代码
    1. @Entity  
    2. public class Person {  
    3.   
    4.     @Id  
    5.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
    6.     private int id;  
    7.   
    8.     @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "Person  
    9. ")  
    10.     private Picture picture;  
     
    Java代码
    1. @Entity  
    2. public class Picture {  
    3.     @Id  
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
    5.     private int id;  
    6.   
    7.     @OneToOne  
    8.     private Person Person;  
    9.   
    [java] view plaincopy
     
    1. <span style="font-size: medium;">@Entity 
    2. public class Picture { 
    3.     @Id 
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY) 
    5.     private int id; 
    6.  
    7.     @OneToOne 
    8.     private Person Person; 
    9.  
    10. </span> 
    [java] view plaincopy
     
    1. <span style="font-size:14px;">@Entity  
    2. public class Picture {  
    3.     @Id  
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
    5.     private int id;  
    6.   
    7.     @OneToOne  
    8.     private Person Person;  
    9.   
    10. }  
    11. </span>  

    主表是Picture,从表是Person.外键字段定义在Picture表中.在这种情况下.读取Person会现实的读取Picture.

    因为如果延迟加载要起作用,就必须设置一个代理对象.但是Personn可以不关联一个Picture,如果有Picture关联就设置为代理对象延迟加载,如果不存在Picture就设置null,因为外键字段是定义在Picture表中的,Hibernate在不读取Picture表的情况是无法判断是否关联有Picture,因此无法判断设置null还是代理对象,统一设置为代理对象,也无法满足不关联的情况,所以无法使用延迟加载,只有显示读取Picture.

    原因找到了.做了如下修改

    Person 代码
    1. @Entity  
    2. public class Person {  
    3.   
    4.     @Id  
    5.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
    6.     private int id;  
    7.   
    8.     @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)  
    9.     private Picture picture;  
     
    Java代码
    1. @Entity  
    2. public class Picture {  
    3.     @Id  
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
    5.     private int id;  
    6.   
    7.     @OneToOne(mappedBy = "picture)  
    8.     private Person Person;  
    9.   
    [java] view plaincopy
     
    1. <span style="font-size: medium;">@Entity 
    2. public class Picture { 
    3.     @Id 
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY) 
    5.     private int id; 
    6.  
    7.     @OneToOne(mappedBy = "picture) 
    8.     private Person Person; 
    9.  
    10. </span> 
    [java] view plaincopy
     
    1. <span style="font-size:14px;">@Entity  
    2. public class Picture {  
    3.     @Id  
    4.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
    5.     private int id;  
    6.   
    7.     @OneToOne(mappedBy = "picture)  
    8.     private Person Person;  
    9.   
    10. }  
    11. </span>  

    修改了表的主从关系,这时外键字段定义在Personnel表中.Hibernate就可以在不读取Picture表的情况下根据外键字段设置null或者代理对象,延迟加载也就起作用了.

    同样的道理,我们平时在使用一对多的情况是,多端是主表,因此可以通过外键字段判断进而设置代理对象或者null.而在一端,虽然 Hibernate无法判断是否关联有对象.但是即使不关联对象时也不应该设置为null,而应该设置为一个空的List或者Map,那么 Hibernate就可以通过代理这个List或者Map实现延迟加载.这也是为什么,我们在设置一端关联时,一般显式的new一个ArrayList或者HaskMap,如:

    Java代码
    1. @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy ="personnel")  
    2. private List<Reward> rewards = new ArrayList<Reward>(); 
    [java] view plaincopy
     
    1. <span style="font-size: medium;">@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "personnel") 
    2. private List<Reward> rewards = new ArrayList<Reward>();</span> 
    [java] view plaincopy
     
    1. <span style="font-size:14px;">@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "personnel")  
    2. private List<Reward> rewards = new ArrayList<Reward>();</span>  

    这就是为了避免使用null表示没有关联,和使用空的List一致.

  • 相关阅读:
    每日一题计划
    acm新手刷题攻略之poj
    Swift几行代码设置UIcollectionView的section底色,圆角
    简单几行代码设置UIcollectionView底色、section背景底色、背景色、背景阴影、背景圆角,支持CollectionView内容左对齐、居中对齐、右对齐、右对齐且右开始排序,支持底色点击反馈
    iOS12 EachNavigationBar导航栏操作出现黑边解决办法
    EachNavigationBar 导航栏颜色与给定颜色不相同设定
    详解冒泡排序法
    递归的简单用法
    判断一个整数是否为素数(质数)
    tcp黏包与拆包
  • 原文地址:https://www.cnblogs.com/gtaxmjld/p/4443111.html
Copyright © 2011-2022 走看看