使用延迟初始化属性分离JPA对象 [英] Detach JPA objects with lazy initialized properties

查看:125
本文介绍了使用延迟初始化属性分离JPA对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有两个JPA实体:用户和具有一对多关系的订单。

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

私人长ID;
私人套餐<订单>命令;
$ b $ public User(){}

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


@OneToMany(mappedBy =user,cascade = CascadeType.PERSIST,fetch = FetchType.LAZY)
@LazyCollection(LazyCollectionOption.EXTRA)
public设置<排序> getOrders(){
返回订单;
}
public void setOrders(Set< Order> orders){
this.orders = orders;
}
}


/ **
*订单DTO
* /
@实体
@表(name =order)
public class Order实现Serializable {
private static final long serialVersionUID = 84504362507297200L;

私人长ID;
私人用户用户;

public Order(){
}

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

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




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

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

退货单;
}

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



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

  @Transactional(readOnly = true)
public设置<排序> getOrders(){
Set< Order> orders = user.getOrders(); (订单:订单)


entityManager.detach(订单);
退货单;

没有任何变化:($ / b
$ b

对于我来说,关于用户是否参加一组订单并不重要,我只想使用这套设备而不会修改它。



任何人都可以帮助我吗?)

解决方案


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


这个错误是自我解释的:你正试图加载一个(懒惰)加载的集合,但没有活动会话,因为 User 实例被分离。


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


这不会改变任何事情。 EntityManager#detach(Object) 方法不会加载任何东西,它会从持久化上下文中移除传入的实体,使其脱离 / em>。


这对我来说无关紧要,关于用户是否参加了一组订单。我只想使用这个集合并且不会修改它。


您需要创建关联EAGER(以便订单将在检索用户时加载)或在检索服务中的用户时使用FETCH JOIN:

  SELECT u 
FROM用户你在哪里取消取消u.orders
在哪里u.id =:id







我是否正确理解hibernate没有强制加载当前对象的所有惰性关联的标准机制


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


我没有办法让hibernate忽略当前对象的延迟关联(将它们设置为null)

什么?你忽略了什么意思?为什么你会这样做?


There are two JPA entities: User and Order with one-to-many relationship.

/**
 * 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;
    }
}

I use these entities in my service layer classes where every method runs in transaction. Everything is fine except cases when methods of service layer classes must return these entities.

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

    return orders;
}

This method returns data well. But when I try access to received collection elements I catch exception: "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: package.User.orders, no session or session was closed".

So, it was excepted. I thought that detaching result will solve my problem, but trick like this

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

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

didn't change anything :(

It doesn't matter for me will info about users attend in set of orders or not. I just want to work with this set and not going to modify it.

Can anybody help me? :)

解决方案

This method returns data well. But when I try access to received collection elements I catch exception: "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: package.User.orders, no session or session was closed".

The error is self explaining: you are trying to load a (lazy) loaded collection but there is no active session anymore because the User instance is detached.

So, it was excepted. I thought that detaching result will solve my problem, but trick like this

This won't change anything. The EntityManager#detach(Object) method doesn't load anything, it removes the passed entity from the persistence context, making it detached.

It doesn't matter for me will info about users attend in set of orders or not. I just want to work with this set and not going to modify it.

You need to either make the association EAGER (so that Orders will be loaded when retrieving a User) or to use a FETCH JOIN when retrieving a user in your service:

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


Do I understand correctly that hibernate has no standard mechanism for force load all lazy associations of current object

Hibernate has a Hibernate.initialize method, but this is obviously not standard JPA (prefer fetch join for portable code).

I have no way to make hibernate ignore lazy associations of current object (set them as null)

What? What do you mean by ignore? Why would you do that anyway?

这篇关于使用延迟初始化属性分离JPA对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆