【问题标题】:How to better avoid the LazyInitializationException?如何更好地避免 LazyInitializationException?
【发布时间】:2011-06-23 16:12:32
【问题描述】:

目前我有一个子实体与它的父实体有一个@ManyToOne 关联。以前的开发人员已将此字段设置为lazy="false",以便在会话关闭时也可以在需要时获取父级,但是我决定它应该是lazy="true",因为它并不总是使用,但是这样做时我遇到了LazyInitializationException,因为会话已关闭,并且子级在尝试获取父级时与会话分离。

我想知道将run 方法的更多逻辑移动到与DAOs 交互的服务类中是否正确,因此我可以避免异常,因为目前服务类就像普通类一样注入所需的DAOs,他们只需调用DAO 方法并返回结果。 我是否应该在与实体交互的服务类中放置更多方法,这将获取用户并检查所有登录操作,如果需要,获取父级,然后将登录结果返回到 run 方法..

public class Login extends Runnable {
     private UserService userService;
     ...
     public void run() {
         ...
         User user = userSerivce.getById(id);
         Account account = user.getAccount(); //LazyInitializationException
         ...
         if (account.isLocked()) {
             ...
         }
         ...
         userService.save(user);

         //Send some message to the user..
     }
}

public class UserServiceImpl implements UserService {
    private UserDAO userDAO;
    ...
    public User getById(long id) {
        return userDAO.getById(id);
    }
    public void save(User user) {
        userDAO.save(user);
    }
}

public UserDAOImpl implements UserDAO {
    private SessionFactory factory;
    ...
    public User getById(long id) {
        return (User) factory.getCurrentSession().load(User.class, id);
    }
    public void save(User user) {
        factory.getCurrentSession().saveOrUpdate(user);
    }
}

我使用 Spring 的 <tx:advice> 来处理关闭和其他与事务相关的事情。

【问题讨论】:

  • 你有什么接口?网页界面?还是远程客户端?
  • 那个运行方法是什么?我不能很好地理解你,但我认为这项工作应该在服务层完成,所以如果它有一个关联的数据库会话,它可能会从惰性关联中获取数据。如果您出于任何原因不想这样做,您可以在会话打开时强制初始化惰性字段并稍后使用它。在休眠中,您可以使用 'Hibernate.initialize(myBean.getMyLazyValue());'
  • 注意第二段不清楚。我们不知道您的代码是什么样子...
  • 对不起,添加了代码示例!希望现在有意义。
  • @Puce,它不是一个网络应用程序,不。就像游戏服务器一样。

标签: java business-logic service-layer lazy-initialization


【解决方案1】:

我更喜欢让我的所有实体关系都懒惰,因为我不知道是否以及何时需要这些外部实体。这样,当我不需要其他实体时,我可以避免不必要的连接。如果我最终需要实体,我会创建一个命名查询并急切地获取实体或集合。这是example

我同意您应该将 DTO 而不是实体发送回您的调用前端应用程序。 Hibernate 实体充满了代理,将它们发回将是低效的。我不确定您是将这些对象发送到 jsp/velocity/etc 文件还是外部应用程序,但如果您要发送回 JSON 或类似于调用应用程序的东西,我建议您使用 DTO。这是另一个与 DTO 的 click here 相关的问题,它讨论了 2 个易于转换的框架。

【讨论】:

  • 不,不要将这些发送到任何地方。他们只是呆在那里,用户会收到从实体以字符串形式传输的所需内容的响应。谢谢你。
【解决方案2】:

创建 DTO,不要通过网络发送 JPA 实体。

当您创建 DTO 时,您必须访问所需的属性,以及触发加载它们的原因。

【讨论】:

  • 我不通过网络(工作)发送实体。嗯,你能举一些DTOs 的例子吗?
  • 问题是:服务端和客户端运行在同一个JVM上吗?如果不使用 DTO
  • 是的,他们是......这是一个套接字服务器,最终用户在 Flash 播放器中。
  • DTO 是数据的客户端视图,通常独立于任何服务器端持久性机制。这是一种设计模式。你可以查一下。
猜你喜欢
  • 1970-01-01
  • 2011-04-04
  • 2021-09-19
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 2022-06-10
相关资源
最近更新 更多