如何更好地避免LazyInitializationException?
目前,我有一个子实体,它与其父实体有 @ManyToOne
关联。以前的开发人员已将此字段设置为 lazy="false"
以便在会话关闭时在需要时获取父级,但我认为它应该是 lazy="true"
因为它并不总是被使用,但这样做时我遇到了 LazyInitializationException ,因为会话已关闭,并且子级在尝试获取父级时与会话分离。
我想知道将 run
方法的更多逻辑移动到与 DAO
交互的服务类是否正确,这样我就可以避免异常,因为目前服务类就像普通类一样,注入了所需的 DAO,它们只调用 DAO 方法并返回结果。 我是否应该在服务类中放置更多与实体交互的方法,这将让用户并检查登录操作的所有内容,如果需要则获取父级,然后将登录结果返回到运行方法..
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 的
来处理关闭和其他与事务相关的内容。
Currently I have a child entity that has a @ManyToOne
association to it's parent entity. Previous developers have set this field as lazy="false"
to get the parent whenever needed when the session is closed too, however I decided it should be lazy="true"
as it's not always used but when doing so I ran into LazyInitializationException
because the session is closed and the child is detached from the session when it tries to get the parent.
I was wondering if it's right to move some more logic of the run
method as seen bellow to the service class which interacts with DAO
s thus I could avoid the exception because currently the service classes are like plain classes which have the needed DAO
s injected and they just call the DAO
method and returns the result.
Should I put like more methods in the service class which interact with the entities, which would get the user and check everything for log in action, get parent if needed and then just return the log in result to run
method..
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);
}
}
I use Spring's <tx:advice>
to handle the closing and other transaction related stuff.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我更喜欢让所有实体关系都是惰性的,因为我不知道是否以及何时需要这些外部实体。这样,当我不需要额外的实体时,我可以避免不必要的连接。如果我最终需要该实体,我会创建一个命名查询并急切地获取该实体或集合。这是一个 示例< /a>.
我确实同意您应该将 DTO 而不是实体发送回您的调用前端应用程序。 Hibernate 实体充满了代理,将它们发送回来效率很低。我不太确定您是否要将这些对象发送到 jsp/velocity/etc 文件或外部应用程序,但如果您要发回 JSON 或类似于调用应用程序的内容,我建议使用 DTO。这是另一个涉及 DTO 的单击此处的问题,讨论了 2易于转换的框架。
I prefer to have all of my entity relationships as lazy since I don't know if and when I'll need those external entities. This way I can avoid unnecessary joins when I don't need the additional entities. If I do end up needing the entity I create a named query and eager fetch the entity or collection. Here's an example.
I do agree though that you should be sending a DTO instead of the entity back to your calling front end application. Hibernate entities are full of proxies and it would be inefficient to send them back. I'm not really sure if you are sending these objects to a jsp/velocity/etc file or to an external application but I would recommend using a DTO if you are sending back JSON or something similar to the calling application. Here's another question that deals with DTO's click here that discusses 2 frameworks for easy conversion.
创建 DTO,不要通过网络发送 JPA 实体。
创建 DTO 时,您必须访问所需的属性,这些属性将触发加载它们。
Create DTOs, don't send JPA Entities over the net.
When you create the DTOs, you will have to access the required properties, what will trigger to load them.