2010-09-04 116 views
4

有两个JPA实体:用户和具有一对多关系的顺序。使用延迟初始化属性分离JPA对象

/** 
* User DTO 
*/ 
@Entity 
@Table(name="user") 
public class User implements Serializable { 
    private static final long serialVersionUID = 8372128484215085291L; 

    private Long id; 
    private Set<Order> orders; 

    public User() {} 

    @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequenceUser") 
    public Long getId() { 
     return this.id; 
    } 
    private void setId(Long id) { 
     this.id = id; 
    } 

    @OneToMany(mappedBy="user", cascade=CascadeType.PERSIST, fetch=FetchType.LAZY) 
    @LazyCollection(LazyCollectionOption.EXTRA) 
    public Set<Order> getOrders() { 
     return orders; 
    } 
    public void setOrders(Set<Order> orders) { 
     this.orders = orders; 
    } 
} 


/** 
* Order DTO 
*/ 
@Entity 
@Table(name="order") 
public class Order implements Serializable { 
    private static final long serialVersionUID = 84504362507297200L; 

    private Long id; 
    private User user; 

    public Order() { 
    } 

    @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequenceOrder") 
    public Long getId() { 
     return this.id; 
    } 
    private void setId(Long id) { 
     this.id = id; 
    } 

    @ManyToOne 
    @JoinColumn(name="user_id") 
    public User getUser(){ 
     return user; 
    } 
    public void setUser(User user){ 
     this.user = user; 
    } 
} 

我在我的服务层类中使用这些实体,其中每个方法都在事务中运行。除了服务层类的方法必须返回这些实体的情况之外,一切都很好。

@Transactional(readOnly=true) 
public Set<Order> getOrders() { 
    Set<Order> orders = user.getOrders(); 

    return orders; 
} 

该方法很好地返回数据。但是,当我尝试访问收到的集合元素时,我发现异常:“org.hibernate.LazyInitializationException:未能懒惰地初始化一个角色集合:package.User.orders,没有会话或会话被关闭”。

因此,它是例外。我认为,分离结果将解决我的问题,而是欺骗这样

@Transactional(readOnly=true) 
public Set<Order> getOrders() { 
    Set<Order> orders = user.getOrders(); 

    for(Order order: orders) 
     entityManager.detach(order); 
    return orders; 
} 

没有改变任何东西:(

它不适合我没关系将有关用户信息的集合订单或不参加我只是想用这组的工作,而不是去修改它。

任何人可以帮助我吗?:)因为数据请求交易之外发生

回答

6

该方法可以很好地返回数据。但是,当我尝试访问收到的集合元素时,我发现异常:“org.hibernate.LazyInitializationException:未能懒惰地初始化一个角色集合:package.User.orders,没有会话或会话被关闭”。

错误是自我解释:您试图加载(懒惰)加载的集合,但由于User实例已分离,因此不再有活动会话。

因此,它是例外。我认为分离结果将解决我的问题,但这样的技巧

这不会改变任何东西。 EntityManager#detach(Object)方法不会加载什么,它将从持久化上下文中删除传递的实体,使其脱离分离

这对我来说无关紧要,关于用户出席一组订单或不。我只想使用这个集合,而不会去修改它。

您需要可以使联想迫切,使用FETCH检索在服务用户时JOIN(使订单将检索用户时加载):

SELECT u 
FROM User u LEFT JOIN FETCH u.orders 
WHERE u.id = :id 

我是否理解正确的话Hibernate没有标准的机制,力负载电流对象的所有延迟关联

Hibernate有一个Hibernate.initialize方法,但这显然不是标准的JPA(更喜欢用于便携式代码的fetch连接)。

我有没有办法让休眠忽略当前的对象(它们设置为NULL)

什么的延迟关联?你忽略了什么意思?你为什么要这样做?

+0

谢谢。我想澄清两点:我是否正确理解hibernate没有强制加载当前对象的所有惰性关联的标准机制 - 只有适当的方法或查询调用?我没有办法让休眠忽略当前对象的惰性关联(将它们设置为空)? – mikhail 2010-09-06 01:22:15

+0

我明白,试图忽视懒惰的尝试是错误的,但我纯粹有学术兴趣。例如,我通过实体管理器获得了User类的对象:“User user = entityManager(User.class,1)”。此时“订单”属性等于空,因为它很懒。是否有可能从休眠状态“分离”对象“用户”,以防止访问方法“getOrders”期间的属性“命令”初始化? – mikhail 2010-09-06 11:09:32

+0

@mikhail'在Hibernate论坛的访问方法“getOrders”中搜索“unproxy”或“deproxy”,是否可以从hibernate中“分离”对象“用户” – 2010-09-07 07:08:50

0

的LazyInitialisationException。如果你需要这些数据,你必须在一个事务中请求它 - 在你的情况下,这将在服务方法中。

您可以通过多种方式请求数据加载。最简单的:

for(Order order: orders) 
    order.getX() 

(其中X是比Id或其他版本的某些属性)

然而,这将加载在一个单独的查询,如果有很多订单是慢的每个订单。更快的方法是发出返回该用户所有订单的查询(JP-QL或Criteria)。 (编辑:查看Pascal的回答以获得合适的查询。)