如何使用传播等待事务提交 REQUIRES_NEW
How to wait for transactions to commit using Propagation REQUIRES_NEW
我想集成测试调用使用 @Transactional(propagation = Propagation.REQUIRES_NEW)
的方法的服务方法。但是,基于内部(新)事务的断言失败。
class MyService {
@Transactional(propagation = Propagation.NESTED)
def method1() {
method2()
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
def method2() {
// some code that will modify the DB
}
}
class MyServiceNonTransactionalIntegrationSpec extends IntegrationSpec {
static transactional = false
def myService = new MyService()
setup() {
// populate database here
}
cleanup() {
// teardown database here after tests complete
}
def method1() {
when: "we test the main method"
myService.method1()
then: "we should be able to see the result of method 1 and method 2"
// BUT: (!!!)
// assertions based on state of database fail, perhaps because new transaction
// wrapped around method 2 has not yet committed
}
}
如何集成测试 method1()
?
编辑:
为了解决代理问题,我尝试了以下方法,但仍然无法正常工作:
class MyService {
def myService2
@Transactional(propagation = Propagation.NESTED)
def method1() {
myService2.method2()
}
}
class MyService2 {
@Transactional(propagation = Propagation.REQUIRES_NEW)
def method2() {
// some code that will modify the DB
}
}
class MyServiceNonTransactionalIntegrationSpec extends IntegrationSpec {
static transactional = false
def myService = new MyService()
def myService2 = new MyService2()
setup() {
myService.myService2 = myService2
// populate database here
}
// rest as before
}
您遇到过自我调用。看这里:Spring - @Transactional - What happens in background? or Spring @Transactional Annotation : Self Invocation
这是我的一篇 类 的摘录:
@Service("authzService")
public class AuthorizationService implements IAuthorizationService {
@Resource(name="authzService")
private IAuthorizationService self;
我将这个私有成员用于带有@Cached 注释的自调用方法。
如果您使用 org.springframework.transaction.annotation.Transactional
,这只是一个自调用问题 - 您应该使用 @grails.transaction.Transactional
,它具有相同的配置选项,但使用 AST 转换而不是运行时代理来避免不调用代理方法的问题。当使用 Grails 注释时,每个方法都被重写以模拟为每个方法创建代理,将代码包装在事务模板中,该模板根据该方法的注释设置配置(在方法上显式,或从 class-作用域注解).
但是您的测试失败了,因为您正在使用 new
创建服务。 始终 在集成测试中使用依赖注入,这样您就可以获得配置好的 Spring bean,而不仅仅是一个新的未初始化的 POGO。为此,请在测试之外添加相同的 属性 语法:
def myService
def myService2
并删除 Spring 为您完成的不必要的接线代码(例如 myService.myService2 = myService2
)。
我想集成测试调用使用 @Transactional(propagation = Propagation.REQUIRES_NEW)
的方法的服务方法。但是,基于内部(新)事务的断言失败。
class MyService {
@Transactional(propagation = Propagation.NESTED)
def method1() {
method2()
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
def method2() {
// some code that will modify the DB
}
}
class MyServiceNonTransactionalIntegrationSpec extends IntegrationSpec {
static transactional = false
def myService = new MyService()
setup() {
// populate database here
}
cleanup() {
// teardown database here after tests complete
}
def method1() {
when: "we test the main method"
myService.method1()
then: "we should be able to see the result of method 1 and method 2"
// BUT: (!!!)
// assertions based on state of database fail, perhaps because new transaction
// wrapped around method 2 has not yet committed
}
}
如何集成测试 method1()
?
编辑:
为了解决代理问题,我尝试了以下方法,但仍然无法正常工作:
class MyService {
def myService2
@Transactional(propagation = Propagation.NESTED)
def method1() {
myService2.method2()
}
}
class MyService2 {
@Transactional(propagation = Propagation.REQUIRES_NEW)
def method2() {
// some code that will modify the DB
}
}
class MyServiceNonTransactionalIntegrationSpec extends IntegrationSpec {
static transactional = false
def myService = new MyService()
def myService2 = new MyService2()
setup() {
myService.myService2 = myService2
// populate database here
}
// rest as before
}
您遇到过自我调用。看这里:Spring - @Transactional - What happens in background? or Spring @Transactional Annotation : Self Invocation
这是我的一篇 类 的摘录:
@Service("authzService")
public class AuthorizationService implements IAuthorizationService {
@Resource(name="authzService")
private IAuthorizationService self;
我将这个私有成员用于带有@Cached 注释的自调用方法。
如果您使用 org.springframework.transaction.annotation.Transactional
,这只是一个自调用问题 - 您应该使用 @grails.transaction.Transactional
,它具有相同的配置选项,但使用 AST 转换而不是运行时代理来避免不调用代理方法的问题。当使用 Grails 注释时,每个方法都被重写以模拟为每个方法创建代理,将代码包装在事务模板中,该模板根据该方法的注释设置配置(在方法上显式,或从 class-作用域注解).
但是您的测试失败了,因为您正在使用 new
创建服务。 始终 在集成测试中使用依赖注入,这样您就可以获得配置好的 Spring bean,而不仅仅是一个新的未初始化的 POGO。为此,请在测试之外添加相同的 属性 语法:
def myService
def myService2
并删除 Spring 为您完成的不必要的接线代码(例如 myService.myService2 = myService2
)。