关于grails:spring/resources.groovy中配置的服务没有Hibernate session

Service configured in spring/resources.groovy does not have a Hibernate session

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

1
2
3
4
5
6
7
public class TaskService {

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

这很好用。

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

1
2
3
4
5
6
7
8
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中添加了特殊服务:

1
2
3
beans = {
        taskService( SpecialTaskService )
}

但是现在我们在特殊服务中调用 "task.save()" 时会得到一个 HibernateException:
org.hibernate.HibernateException: No Hibernate Session bound to thread,并且配置不允许在这里创建非事务性的

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

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

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


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

创建一个普通的新实例

最简单的做法是注释类(如果您愿意,也可以注释单个方法):

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.transaction.annotation.Transactional

@Transactional
class SpecialTaskService extends TaskService {

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

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

1
2
3
4
5
6
7
8
9
10
class SpecialTaskService extends TaskService {

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