繁体   English   中英

@Transactional在@Service中不起作用

[英]@Transactional is not working in @Service

我正在使用Jersey,Spring和Hibernate开发REST API。 我有这个端点:

@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错误:

无法懒惰地初始化角色集合:com.api.blabla.Incidence.questions,没有会话或会话被关闭

questions@OneToMany财产Incidence

如果我在端点方法中放置@Transactional注释,而不是在服务中,它可以正常工作。 但我知道@Transactional必须放在服务级别。

谢谢。

这并不意味着@Transactional不起作用。 它正在做你告诉它要做的事情。 该服务返回一个Incidence实例而没有初始化的questions集合,并且您试图在服务的事务之外访问该集合(可能是在Jersey尝试将其转换为JSON时)。

在这种情况下,服务必须返回调用者所需的所有数据,这意味着您必须在返回结果之前初始化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;
}

您遇到此问题是因为您的交易在您的服务电话上开始和结束。 回想一下Hibernate文档,延迟加载仅适用于Hibernate会话(在这种情况下,hibernate会话以服务调用开始和结束)。 您无法重新连接到hibernate会话(简单地)来初始化集合。

解决这个问题的两种方法:

  1. 您可以将获取类型更改为EAGER,以便以后急切加载控制器内引用的问题

  2. 对服务进行单独查询以从控制器获取有关事件的问题,并在返回响应之前在视图bean中设置响应

此外,作为更好的实践观点的建议,您可能希望将服务方法中的@Transactional注释更改为@Transactional(readOnly = true),以便更好地执行只读调用。

什么初始化可以在这里看到什么做hibernate-initialize-do

也许你必须手动初始化它。 请试试这个:

@Transactional
public List<Incidence> getIncidences() {
  List<Incidence> incidencias = incidencesDao.getIncidences();
  for (Incidence inc : incidencias) {
    inc.getQuestions().size();
  }

  return incidencias;
}

解决了! 我在LAZY获取类型中有Incidence -> questions关系(默认)。 但是,在端点资源方法中,我调用了getQuestions() 此代码不在事务内部,因此它抛出了初始化异常。

我通过将@OneToMany fetch属性@OneToManyEAGER来解决它。

谢谢你的回答。 如果你看不到剩下的代码,你很难帮助我...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM