在spring / resources.groovy中配置的服务没有Hibernate会话

时间:2010-09-12 08:01:36

标签: grails

我们有一个包含服务的插件的应用程序:

public class TaskService {

    public void doSomething( Task task ) {
        // do something with task
        task.save();
    }
}

这很好用。


对于有特殊要求的“特殊”客户,我们有第二个应用程序,其中包含第一个应用程序的插件和另一个为该客户提供特殊服务的插件,该服务扩展了原始服务并覆盖了一些方法:

public class SpecialTaskService extends TaskService{

    @Override
    public void doSomething( Task task ) {
        // do something special with task
        task.save();
    }
}

在注入taskService的第二个应用程序的每个位置,我们现在想要使用SpecialTask​​Service(也在第一个应用程序的插件中)。所以我们在grails-app / conf / spring:

下的resources.groovy中添加了特殊服务
beans = {
        taskService( SpecialTaskService )
}

但是现在我们在特殊服务中调用“task.save()”时会得到一个HibernateException: org.hibernate.HibernateException:没有Hibernate会话绑定到线程,配置不允许在这里创建非事务性的

我们知道我们可以将一个SessionFactory注入到SpecialService中,但是当我们调用sessionFactory.currentSession时,我们会得到相同的异常。

当我们在resources.groovy中配置一个不扩展另一个服务的服务时,也会发生异常。

有没有办法让特殊服务成为某种“hibernateSessionAware”,以便我们可以在域对象上调用save()和merge()?

1 个答案:

答案 0 :(得分:5)

原始服务是事务性的,因此它在方法调用期间保持Hibernate会话打开(除非一个已经处于活动状态且已加入该服务)。因此,您只需告诉Spring使用taskService(SpecialTaskService)

创建一个简单的新实例,因此您需要将其设置为事务性的。

最简单的方法是注释类(或者你喜欢的单个方法):

import org.springframework.transaction.annotation.Transactional

@Transactional
class SpecialTaskService extends TaskService {

   @Override
   void doSomething(Task task) {
      // do something special with task
      task.save()
   }
}

但您也可以在withTransaction块中包装代码块或整个方法:

class SpecialTaskService extends TaskService {

   @Override
   void doSomething(Task task) {
      Task.withTransaction { status ->
         // do something special with task
         task.save()
      }
   }
}