我正在使用Jersey,Spring和Hibernate开发REST API。我有这个端点:
@Service
public class IncidencesService {
@Autowired
IncidencesDAO incidencesDAO;
@Transactional
public List<Incidence> getIncidences() {
List<Incidence> incidencias = incidencesDao.getIncidences();
return incidences;
}
}
和服务:
org.hibernate.LazyInitializationException
但我收到questions
错误:
无法懒惰地初始化角色集合: com.api.blabla.Incidence.questions,no 会议或会议已经结束
@OneToMany
是Incidence
的{{1}}属性。
如果我在端点方法中放置@Transactional
注释,而不是在服务中,它可以正常工作。但我知道@Transactional必须放在服务级别。
感谢。
答案 0 :(得分:4)
这并不意味着@Transactional
无效。它正在做你告诉它要做的事情。该服务返回Incidence
的实例而没有初始化的questions
集合,并且您尝试在服务的事务之外访问该集合(可能是在Jersey试图将其转换为JSON时)。 / p>
在这种情况下,服务必须返回调用者所需的所有数据,这意味着您必须在返回结果之前初始化questions
。因此,只需在服务方法中为您返回的每个实例调用Hibernate.initialize(incidence.getQuestions())
。
@Transactional
public List<Incidence> getIncidences() {
List<Incidence> incidencias = incidencesDao.getIncidences();
for (Incidence inc : incidencias) {
Hibernate.initialize(inc.getQuestions());
}
return incidencias;
}
答案 1 :(得分:1)
您遇到此问题是因为您的交易在您的服务电话中开始和结束。 回想一下Hibernate文档,延迟加载仅适用于Hibernate会话(在这种情况下,hibernate会话以服务调用开始和结束)。您无法重新连接到hibernate会话(简单地)来初始化集合。
解决这个问题的两种方法:
您可以将获取类型更改为EAGER以急切加载 稍后在控制器内引用的问题
对服务进行单独查询以从控制器获取有关事件的问题,并在返回响应之前在视图bean中设置响应
此外,根据更好的实践观点,您可能希望将服务方法中的@Transactional注释更改为@Transactional(readOnly = true),以便更好地执行只读调用。
答案 2 :(得分:0)
您可以在此处看到初始化内容what-does-hibernate-initialize-do
也许您必须手动初始化它。请试试这个:
@Transactional
public List<Incidence> getIncidences() {
List<Incidence> incidencias = incidencesDao.getIncidences();
for (Incidence inc : incidencias) {
inc.getQuestions().size();
}
return incidencias;
}
答案 3 :(得分:0)
解决!我在 LAZY 获取类型(默认)中有Incidence -> questions
个关系。但是,在端点资源方法中,我调用了getQuestions()
。此代码不在事务内部,因此它抛出了初始化异常。
我已将@OneToMany
的抓取属性更改为 EAGER ,从而解决了这个问题。
感谢您的回答。如果你看不到剩下的代码,你很难帮助我......