Wildfly中启用事务解决Hibernate懒加载初始化异常
解决Hibernate LazyInitializationException:正确实现懒加载获取用户Posts
咱们先揪出问题的核心:你加了@Transactional但没生效,导致EntityManager的Session在Service方法执行完就关闭了,后续访问懒加载的posts集合时,因为没有Session可用,就抛出了异常。结合你的技术栈(Wildfly+Hibernate+Java EE MVC),给你几个靠谱的解决方案:
一、确保Service类被容器托管(@Transactional生效的前提)
Java EE中,@Transactional注解只有作用在容器托管的Bean上才会生效,普通类不会被容器处理事务。你的UserService目前没有任何托管注解,所以容器根本没识别到事务配置。
修改你的UserService,添加@Stateless(EJB)或@ApplicationScoped(CDI)注解:
@Stateless // 推荐用EJB的Stateless,Java EE中天然支持事务管理 @Transactional public class UserService { private List<User> users; private Set<Post> posts; @PersistenceContext(unitName = "my-pu") private EntityManager em; public List<User> getUsers() { String qlQuery = "SELECT u FROM User u"; Query query = em.createQuery(qlQuery); users = query.getResultList(); return users; } // 类上已加@Transactional,方法上可以不用重复加 public Set<Post> getUserPosts(Long userId) { String qlQuery = "SELECT u FROM User u WHERE u.id = :userId"; Query query = em.createQuery(qlQuery); query.setParameter("userId", userId); User user = (User) query.getSingleResult(); posts = user.getPosts(); // 事务内Session保持打开,此时访问posts会自动触发懒加载 return posts; } }
二、修正持久化单元的事务类型
你的persistence.xml里transaction-type设为了JPA,但Wildfly是Java EE服务器,默认应该使用JTA事务管理,否则容器的事务控制会失效。
修改persistence.xml的事务类型:
<persistence-unit name="my-pu" transaction-type="JTA">
三、用JOIN FETCH主动加载关联集合(灵活替代懒加载)
如果不想依赖事务保持Session打开,也可以在JPQL查询中直接通过JOIN FETCH一次性加载User和关联的Posts,避免后续触发懒加载。这种方式比饿汉加载(FetchType.EAGER)更灵活,只在需要的时候才加载关联数据。
修改getUserPosts方法的查询语句:
@Transactional public Set<Post> getUserPosts(Long userId) { // JOIN FETCH 会一次性查询User和对应的Posts String qlQuery = "SELECT u FROM User u JOIN FETCH u.posts WHERE u.id = :userId"; Query query = em.createQuery(qlQuery); query.setParameter("userId", userId); User user = (User) query.getSingleResult(); posts = user.getPosts(); // 此时posts已经是初始化完成的集合,无需懒加载 return posts; }
关键注意点
- 饿汉加载(
FetchType.EAGER)之所以不推荐,是因为它会每次查询User都强制加载所有Posts,即使你不需要这些数据,会造成不必要的性能开销。上面的方案要么让懒加载在事务内正常工作,要么按需加载关联数据,都比饿汉加载更合理。 - 确认你的实体类中
posts集合的FetchType是LAZY(默认就是LAZY,无需额外配置)。
内容的提问来源于stack exchange,提问作者Jan Bodnar
相关产品推荐
相关产品推荐

