hibernate 双向 OneToOne fetchType lazy 问题

hibernate 双向 OneToOne fetchType lazy 问题

分类: hibernate2013-06-26 14:54 932人阅读 评论(2) 收藏 举报

转载于: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. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private int id;
  6. @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "Person
  7. ")
  8. private Picture picture;
  9. }

Java代码

  1. @Entity
  2. public class Picture {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private int id;
  6. @OneToOne
  7. private Person Person;
  8. }

[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. @OneToOne
  7. private Person Person;
  8. }
  9. </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. @OneToOne
  7. private Person Person;
  8. }
  9. </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. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private int id;
  6. @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  7. private Picture picture;
  8. }

Java代码

  1. @Entity
  2. public class Picture {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private int id;
  6. @OneToOne(mappedBy = "picture)
  7. private Person Person;
  8. }

[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. @OneToOne(mappedBy = "picture)
  7. private Person Person;
  8. }
  9. </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. @OneToOne(mappedBy = "picture)
  7. private Person Person;
  8. }
  9. </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一致.

时间: 2024-08-12 12:19:09

hibernate 双向 OneToOne fetchType lazy 问题的相关文章

hibernate manytoone中的lazy EAGER

Hibernate中的字段映射中的Fetch有两种方式:EAGER和LAZY Eager:全部抓取 Lazy:延迟抓取 如果在字段中声明为Eager,那么在取得当前Bean时,同时会抓取Bean中的关联Bean值.即数据库查询多次.反之Lazy则在之后抓取提交查询. 比如,有如下声明为Eager的User Bean: @OneToMany(mappedBy="user", cascade=CascadeType.ALL, fetch=FetchType.EAGER) private S

hibernate 双向n-n

域模型: 关系数据模型 双向 n-n 关联需要两端都使用集合属性 双向n-n关联必须使用连接表 集合属性应增加 key 子元素用以映射外键列, 集合元素里还应增加many-to-many子元素关联实体类 在双向 n-n 关联的两边都需指定连接表的表名及外键列的列名. 两个集合元素 set 的table 元素的值必须指定,而且必须相同.set元素的两个子元素:key 和 many-to-many 都必须指定 column 属性,其中,key 和 many-to-many 分别指定本持久化类和关联类

hibernate 双向 1-n(详细分析)

双向 1-n 与 双向 n-1 是完全相同的两种情形 双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然. 域模型:从 Order 到 Customer 的多对一双向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中需定义存放 Order 对象的集合属性 关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键 注意: 当 Session 从数据库中加载 Java 集合时, 创建的是 Hibernate 内

FetchType.LAZY和FetchType.EAGER什么区别

1.FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载. 2.FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载. 3.比方User类有两个属性,name跟address,就像百度知道,登录后用户名是需要显示出来的,此属性用到的几率极大,要马上到数据库查,用急加载: 而用户地址大多数情况下不需要显示出来,只有在查看用户资料是才需要显示,需要用了才查数据库,用懒加载就好了.所以,并不是一登录就把用户 的所有资料都加

hibernate双向一对一

package com.bjsxt.hibernate.oneToOne; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn

Hibernate(四)——缓存策略+lazy

Hibernate作为和数据库数据打交道的框架,自然会设计到操作数据的效率问题,而对于一些频繁操作的数据,缓存策略就是提高其性能一种重要手段,而Hibernate框架是支持缓存的,而且支持一级和二级两种缓存,合理的使用缓存策略可以大大提高我们的操作数据效率,但是利用不能,可能会造成不必要的麻烦.  一,一级缓存(Session缓存):  Session缓存表示将查询结果放置到Session的临时存储空间(一级缓存中).Hibernate框架默认支持一级缓存的.一级缓存的范围较小,一旦Sessio

010一对一 主键关联映射_双向(one-to-one)

²  两个对象之间是一对一的关系,如Person-IdCard(人—身份证号) ²  有两种策略可以实现一对一的关联映射 主键关联:即让两个对象具有相同的主键值,以表明它们之间的一一对应的关系:数据库表不会有额外的字段来维护它们之间的关系,仅通过表的主键来关联. 唯一外键关联:外键关联,本来是用于多对一的配置,但是如果加上唯一的限制之后,也可以用来表示一对一关联关系. 实例场景:人<—-> 身份证号(Person<->IdCard)双向:互相持有对方的引用 IdCard实体类: p

012一对一 唯一外键关联映射_双向(one-to-one)

²  两个对象之间是一对一的关系,如Person-IdCard(人—身份证号) ²  有两种策略可以实现一对一的关联映射 主键关联:即让两个对象具有相同的主键值,以表明它们之间的一一对应的关系:数据库表不会有额外的字段来维护它们之间的关系,仅通过表的主键来关联. 唯一外键关联:外键关联,本来是用于多对一的配置,但是如果加上唯一的限制之后,也可以用来表示一对一关联关系. 实例场景:人<—-> 身份证号(Person<->IdCard)双向:互相持有对方的引用 对象模型(唯一外键关联映

Hibernate 双向 多对一

双向多对一和单向多对一唯一不同的地方是多对一的一那端增加了到多那端的映射关联,参照模型还是顾客(customer)-订单(order) package com.demo.model.many2one.both; import java.util.HashSet; import java.util.Set; public class Customer { private Integer id; private String name; private Set<Order> orders = ne