我的服务层上的交易

时间:2015-03-24 03:04:09

标签: hibernate transactions hibernate-session

我有一个已标记为@Transactional的服务。唯一的问题是,我正在研究在调用save方法时需要提交它的对象的方法。

我已经从类级别删除了注释,并将每个方法标记为@Transactional除了我的方法(DAO也标记为@Transactional)。我确实看到我的信息现在就像我想要的那样立即保存,但是当我尝试做一个findBy时,我得到“会话在线程中不存在”异常。

是否有人知道此问题以及如何解决此问题?

1 个答案:

答案 0 :(得分:2)

因此,我不得不对您的方法正在进行一些有根据的猜测,因为您还没有向我们提供有关您的服务类和DAO正在做什么的任何详细信息。

首先,使用@Transactional标记服务方法是最佳做法,因为您的服务类应该是管理您的事务会话的服务类。您的DAO应该仅用于访问数据库并在表单中返回您的对象,以便您可以使用它们。会议不是DAO应该担心的事情。

现在我猜你的服务类看起来像这样:

@Transactional
public void saveOrUpdateFoo(Foo foo){
    fooDao.saveOrUpdate(foo);
}

@Transactional
public Foo manipulateFoo(Foo foo){
    //Do stuff to your Foo object that you want to be changed.
    saveOrUpdateFoo(foo);
    //Database hasn't actually changed yet.
    foo = fooDao.findBy(foo.getFooId());
    //nothing will change here.
}

要了解调用saveOrUpdateFoo(foo)时数据库实际没有变化的原因,您需要了解@Transactional注释实际上导致Hibernate的作用。当您将方法标记为@Transactional时,您告诉Hibernate此方法中的所有内容都需要在单个数据库会话中发生,并且如果出现问题则应该回滚它。

为了实现这一点,当您在DAO中调用currentSession().save(foo);时(我假设您正在这样做),Hibernate将获取您的对象,并更新其本地克隆'在记忆中的那个对象(这实际上并不是它的工作原理,只是想象一下Hibernate在启动事务时根据数据库保留了自己的对象副本,当你调用save / update时它会更改这些副本)

当你的@Transactional方法退出时,Hibernate会将这些更改刷新到数据库,这是数据库状态实际发生变化的时候。如果此对象是新对象(如数据库必须创建新记录),则在使用保存数据库时将使用的值调用saveOrUpdateFoo时,Hibernate应更新它管理的任何ID字段。你不应该需要重新获取'保存后,您的对象应该处于一种状态,就好像您实际上INSERT将其放入数据库中,然后再SELECT再次进行,没有实际上持续改变数据库。

这不应该是一个问题,除非你试图在另一个线程中从数据库中获取对象,而这一切都在进行,在这种情况下,你需要重新设计你的服务类,这样才能解决问题。 #39; t发生。

如果这不能解决您的问题,请发布您的服务类和DAO,以及您实际尝试做的解释。