[英]Spring Transaction Propagation on Class to Class level and Method to Method Level
[英]Grails or Spring Method Level Transaction
我是春季/春季交易的新手,阅读后仍然不清楚,所以我将其发布在这里,
我有一个注释为@Transactional的服务类,并且我有一些方法被注释为
@Transactional(propagation = Propagation.REQUIRES_NEW)
其中一些不是。
@Transactional
class SomeService {
def findJob() {
MyInstance myInstance = getMeAJob();
if (myInstance) {
doSomeThing(myInstance)
doTask()
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception)
private doSomeThing(MyInstance myInst) {
myObj = MyInstance.lock(myInst.id)
try {
differentObj = doTask(myObj)
myObj.save()
doAnotherThing()
}
} catch (Exception e) {
log("Error in doAnotherTask")
}
}
private doAnotherThing(MyInstace myInst) {
perform some update on myInst
myInstant.save(flush: true)
}
private doTask() {
}
将在t2中执行的方法doSomeThing()-在发生异常的情况下不会影响“ t1”(回滚)
doAnotherThing()方法将使用哪种方法? 因为我从doSomething()调用它?
当您具有类作用域注释时,任何未注释的方法都将使用这些设置,并且带注释的方法将使用该注释中的设置覆盖类级别的设置。
但是请注意,在使用Spring的注释支持(使用@org.springframework.transaction.annotation.Transactional )时,仅支持公共方法。 不会有错误,但是注释会被忽略。
但是,即使将doSomeThing公开(通过隐式删除private关键字或显式地将其更改为public ),当您从findJob调用doSomeThing时,它也不会达到您的期望。 这是因为Spring的注释会在运行时触发类的代理的创建。 在这种情况下,为您的服务注册的Spring bean是一个代理实例,该代理实例具有您的类的“真实”实例作为其委托。 所有事务公共方法都被代理拦截,代理开始/加入/等。 交易,然后调用您的服务方法。 一旦在服务实例中的代理“之下”,所有方法调用都是直接的,并且任何注释设置均无效。 要使其正常工作,您需要在Spring bean上调用方法并通过代理来启动新事务。
为避免此代理问题,请改用Grails @grails.transaction.Transactional批注。 它支持与Spring注释相同的事务功能,但不是创建代理,而是AST转换重写您的方法以将它们包装在事务中。 这样就可以像执行操作一样进行直接方法调用,并创建新事务或在注释属性定义的其他事务语义下运行。
一段时间以前,我曾谈过在Grails中使用事务的问题,这可能会有所启发。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.