java@Transactional在@Service中不工作
我正在用Jersey、Spring和Hibernate开发RESTAPI。我有一个端点:
@Path("incidences")
public class IncidencesResource {
@InjectParam
IncidencesService incidencesService;
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Incidence> getIncidences(
@QueryParam("lastupdate") String lastUpdate) {
return incidencesService.getIncidences();
}
以及服务:
@Service
public class IncidencesService {
@Autowired
IncidencesDAO incidencesDAO;
@Transactional
public List<Incidence> getIncidences() {
List<Incidence> incidencias = incidencesDao.getIncidences();
return incidences;
}
}
但是我得到一个org.hibernate.LazyInitializationException
错误:
Failed to lazily initialize a collection of role: com.api.blabla.Incidence.questions, no session or session was closed
questions
是Incidence
的@OneToMany
属性
如果我将@Transactional
注释放在端点方法中,而不是放在服务中,它会正常工作。但我知道@Transactional必须放在服务级别
谢谢
# 1 楼答案
解决了!我在LAZY获取类型(默认)中有
Incidence -> questions
关系。但是,在端点资源方法中,我调用了getQuestions()
。此代码不在事务中,因此引发初始化异常我通过将
@OneToMany
的fetch属性更改为EAGER解决了这个问题谢谢你的回答。如果你看不到剩下的代码,你很难帮助我
# 2 楼答案
这并不意味着
@Transactional
不起作用。它在做你让它做的事。该服务返回一个Incidence
实例,但未初始化questions
集合,您试图在服务事务之外访问该集合(可能是Jersey试图将其转换为JSON时)在这种情况下,服务必须返回调用者所需的所有数据,这意味着您必须在返回结果之前初始化
questions
。所以,只需为您返回的每个实例调用Hibernate.initialize(incidence.getQuestions())
in服务方法# 3 楼答案
您遇到此问题是因为您的事务在服务调用时开始和结束。 回想一下Hibernate文档,惰性加载只在Hibernate会话中起作用(在本例中,Hibernate会话以服务调用开始和结束)。无法(简单地)重新连接到hibernate会话以初始化集合
解决此问题的两种方法:
您可以将fetch类型更改为急切地加载 稍后控制器内部引用的问题
对服务进行单独查询,从控制器获取事件的问题,并在返回响应之前在视图bean中设置响应
此外,从更好的实践角度来看,您可能希望将服务方法中的@Transactional注释更改为@Transactional(readOnly=true),以提高只读调用的性能
# 4 楼答案
你能在这里看到什么what-does-hibernate-initialize-do
也许你必须手动初始化它。请试试这个: