首页 > 解决方案 > 处理 LazyInitializationException 的最佳方法是什么

问题描述

我最近一直在与 Hibernate 作斗争。我最近遇到了一个问题,希望能得到一些帮助。我有两个实体:

1.用户

@Entity
public class User{

@ID
private Long id;

@OneToMany (mappedBy = "user")
private Set<Activity> activities;

...
}

2.活动:

@Entity
public class Activity {

@ID
private Long id;

@ManyToOne
private User user;

...
}

所以在这里,由于我没有将用户活动 fetchType 设置为 EAGER,所以当我从数据库中获取用户实体时,所有活动都将被延迟获取。

我在 UserRepository 中所做的是:

@Override
public User getUserByUserName(String userName) {
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    Query query = entityManager.createQuery
            ("from User u where u.userName = :user_name", User.class);
    query.setParameter("user_name", userName);
    try{
        return (User) query.getSingleResult();
    } catch(NoResultException e) {
        return null;
    } finally {
        entityManager.close();
    }
}

当我想使用获取的用户的活动时,这样做我得到了 LazyInitializationException。但我所做的是从代码中删除 finaly 块:

@Override
public User getUserByUserName(String userName) {
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    Query query = entityManager.createQuery
            ("from User u where u.userName = :user_name", User.class);
    query.setParameter("user_name", userName);
    try{
        return (User) query.getSingleResult();
    } catch(NoResultException e) {
        return null;
    }
 }

这解决了异常。我想知道这是否是正确的方法,还是应该将用户活动 fetchType 更改为 EAGER?

标签: javahibernate

解决方案


规则是

实体不应逃脱交易界限

延迟加载是 Hibernate 的杀手锏,你不必害怕。

因此,存储库/DAO 应该返回实体。该服务应该是事务性的(*),管理实体但在外部返回 DTO。

考虑为此目的使用任何 java bean 映射器以避免猴子工作。

这允许您在不需要时不加载不必要的属性。

(*) 如果没有长期存在的操作,例如 http 调用。


推荐阅读