根据官方文件和我读过的书,服务是跨国的。然而,即使我们立即抛出RuntimeException,我们也会提交记录。
例如:
class MyService {
def someMethod() {
new someDomainObject().save(failOnError:true)
throw new RuntimeException("rollback!")
}
}
并如此称呼它:
class myController{
MyService myService
def someMethod() {
myService.someMethod()
}
}
在上面的例子中,在调用调用服务的控制器,然后检查行是否是通过使用mysql工作台连接到DB创建的之后,该行确实被提交,并且没有回滚。
所以我们接下来尝试了这个:
class MyService {
static transactional = true
def someMethod() {
new someDomainObject().save(failOnError:true)
throw new RuntimeException("rollback!")
}
}
同样的问题。
接下来我们尝试了这个:
@Transactional
class MyService {
static transactional = true
def someMethod() {
new SomeDomainObject().save(failOnError:true)
throw new RuntimeException("rollback!")
}
}
最后,这是可行的。然而,我们不明白为什么。
注:Grails 2.4.4使用MYSQL:
development {
dataSource {
dbCreate = "create-drop"
url = "jdbc:mysql://127.0.0.1:3306/db"
username = "user"
password = "***"
}
}
这是正常行为吗
@Transactional与static transascional=true不同吗?
服务类是intellij14使用Grails视图中Services文件夹中的"newgroovyclass"选项生成的。"new Grails Service"选项对我们不起作用,它什么都不起,所以我们必须在正确的位置"手动"创建所有groovy类。
确定,找到原因,或找到:
"用Transactional注释服务方法将禁用该服务的默认Grails事务行为"
因此,我碰巧将服务中的许多方法中的一个注释为@Transactional(propagation=Propagation.REQUIRES_NEW)
,认为其他方法将保留其默认的transactional,但不,如果您进行任何声明,它将静默地删除所有其他方法的transactionalbehavior,即使您说"static transactional = true
"
这看起来相当危险,从现在起,我将用@Transactional
注释每个服务类,以避免被发现。
这没有多大意义。服务的所有不同变体的功能都应该相同。所使用的一般逻辑是在类级别或至少一个方法上查找@Transactional
。如果使用org.springframework.transaction.annotation.Transactional
,则会创建一个事务代理。如果使用较新的grails.transaction.Transactional
,那么AST将重写方法以使用事务模板,但最终效果基本相同。如果没有注释,那么除非您有static transactional = false
,否则服务是事务性的,并且会创建一个Spring代理(与在类级别包含Spring @Transactional
注释相同)。static transactional = true
是默认值,因此永远不需要;服务完全非事务性的唯一方法是包括CCD_ 10并且不具有CCD_。
可能发生的一件事是,底层表可能不是事务性的。MySQL的较新版本默认使用InnoDB作为表类型,但在5.5之前,默认使用MyISAM。Grails自动检测数据库并为您注册Hibernate方言,这在除MySQL+MyISAM之外的大多数情况下都能很好地工作。为了确保始终使用InnoDB,请在DataSource.groovy中指定适当的方言,例如
dataSource {
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
}
这只会对Hibernate创建的新表有所帮助。请确保将任何现有的MyISAM表转换为InnoDB(尽管在这种情况下,由于您使用的是create-drop,因此不需要转换)。
对于经过多年询问后提出这个问题的人来说,自从Grails 3.1以来,这个问题已经改变了。如今,在Grails 5.2.5中,默认情况下服务不是事务性的。";静态事务";房地产什么都不做了。您可以通过使用@Transactional
对服务进行注释来使其具有事务性
关于这一变化,这里有更多的说法:https://docs.grails.org/latest/guide/services.html#declarativeTransactions