hibernate 双向 OneToOne fetchType lazy 问题

转载于: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.   
  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> 
@Entity
public class Picture {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;

	@OneToOne
	private Person Person;

}

主表是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.   
  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> 
@Entity
public class Picture {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;

	@OneToOne(mappedBy = "picture)
	private Person Person;

}

修改了表的主从关系,这时外键字段定义在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>(); 
  1. <span style="font-size: medium;">@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "personnel"
  2. private List<Reward> rewards = new ArrayList<Reward>();</span> 
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "personnel")
private List<Reward> rewards = new ArrayList<Reward>();

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


原文出处 http://mshijie.javaeye.com/admin/blogs/440057
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值