我正在阅读services上的Grails文档,其中大量提及事务/事务性,但没有真正定义事务性服务方法的真正含义。
鉴于服务的性质,它们经常需要交易行为。
这究竟是什么意思? 事务性方法只是那些使用JPA / JDBC与关系数据库通信的方法,还是它们适用于JTA涵盖的任何内容?
我是否有任何理由不提出服务类@Transactional
,以防某些事情发展到某一天使用交易?换句话说,是否存在使所有服务方法成为交易的性能问题?
答案 0 :(得分:7)
Grails服务默认为交易式服务 - 如果您不希望服务具有交易性,则需要删除所有@Transactional
注释(Grails' @grails.transaction.Transactional
和Spring&#39 ; s @org.springframework.transaction.annotation.Transactional
)并添加
static transactional = false
如果您没有使用transactional
属性禁用交易并且没有注释,则该服务的工作方式与使用Spring注释进行注释的方式相同。也就是说,在运行时,Spring会创建一个类的CGLIB代理,并将代理的实例注册为Spring bean,并将其委托给实际类的实例来执行数据库访问和业务逻辑。这允许代理拦截所有公共方法调用并启动新事务,加入现有事务,创建新事务等。
较新的Grails注释具有与Spring注释相同的所有设置,但它的工作方式略有不同。不是触发单个代理的创建,而是在编译期间通过AST变换重写每个方法,实质上为每个方法创建一个迷你代理(这显然是一种简化)。这样做更好,因为数据库访问和事务语义是相同的,但如果从另一个使用不同设置注释的方法调用一个带注释的方法,则将遵循不同的设置。但是使用代理,它是委托实例内的直接调用,并且代理被绕过。由于代理具有创建新事务或使用其他不同设置的所有逻辑,因此这两种方法将使用第一种方法的设置。使用Grails注释,每种方法都可以按预期工作。
交易方法涉及的性能很小,如果有大量呼叫和/或大量流量,这可能会累积。在代码运行之前,会启动一个事务(假设一个事务处于非活动状态),为此,必须从池中检索连接(DataSource)并配置为关闭自动提交,并进行各种事务设置(隔离) ,超时,只读等)必须制作。但Grails DataSource实际上是一个围绕着"真实"一。在您开始查询之前,它不会获得真正的JDBC连接,因此在此之前缓存所有配置设置,然后重播"在真正的连接上。如果该方法不进行任何数据库工作(或者因为它从未执行过,或者因为它在db访问代码触发之前基于某些条件而提前退出),那么基本上没有数据库成本。但如果确实如此,那么事情就会按预期发挥作用。
不要依赖于这种DataSource代理逻辑 - 最好明确哪些服务是事务性的,哪些服务不是,并且在每个服务中哪些方法是事务性的,哪些不是&#&# 39;吨。最好的方法是根据需要注释方法,或者如果所有方法都使用相同的设置,则在类级别添加单个注释。
您可以在this talk获取有关Grails中交易的更多信息。
答案 1 :(得分:4)
首先,如果您的性能问题是由于您的服务是交易性的,那么您已达到了必杀技。我之所以这么说,是因为在您的应用程序中存在大量其他瓶颈,这是一个主要(甚至是次要的)问题。所以,不要担心这一点。
通常在Grails中,transaction
与数据库连接或休眠会话的事务状态有关。虽然它可以是JTA通过适当的Spring配置管理的任何东西。
简单来说,它通常意味着(默认情况下)数据库事务。