在我的Hibernate事实摘要中 ,我解决了一些关于Hibernate的误解:很多使用Hibernate(包括我自己)的开发人员有时由于缺乏知识而无法正确使用它。 对于许多复杂的产品也可以这样说,但是本周当我在Spring框架中遇到这样的事情时,我真是傻眼了。 当然,像Spring这样务实的东西在其API的某个角落不会有阴影区域。
关于Spring的声明式事务边界
好吧,关于声明式事务边界,我发现了至少一个:
Spring建议您仅使用
@Transactional
注释对具体类(以及具体类的方法)进行注释,而不是对接口进行注释。 您当然可以在接口(或接口方法)上放置@Transactional
批注,但这仅在您使用基于接口的代理时才可以预期。 Java注释不是从接口继承的事实意味着,如果您使用的是基于类的代理(proxy-target-class="true"
)或基于编织的方面(mode="aspectj"
),则事务设置为代理和编织基础结构无法识别该对象,并且该对象也不会包装在事务代理中,这肯定是不好的。
你猜怎么了? 尽管将交易行为作为合同的一部分会很好,但遗憾的是事实并非如此,因为它取决于您的上下文配置,如文档中所述! 可以肯定的是,我尝试过,这是(可悲的)事实。
考虑以下合同和实施:
publicinterfaceService{
voidforcedTransactionalMethod();
@Transactional
voidquestionableTransactionalMethod();
}
publicclassImplementedServiceimplementsService{
privateDummyDaodao;
publicvoidsetDao(DummyDaodao){
this.dao=dao;
}
@Transactional
publicvoidforcedTransactionalMethod(){
dao.getJdbcTemplate().update("INSERT INTO PERSON (NAME) VALUES ('ME')");
}
publicvoidquestionableTransactionalMethod(){
dao.getJdbcTemplate().update("INSERT INTO PERSON (NAME) VALUES ('YOU')");
}
}
现在,根据我们是否激活CGLIB代理, questionableTransactionMethod
行为有所不同,在一种情况下提交,在另一种情况下提交。
对于Eclipse用户-即使没有Spring IDE,当对新属性进行CTRL-spacing时,它也会显示为帮助弹出窗口(尽管XML中已经存在该属性时,它不会显示)。
代理模式的其他事实
Spring的文档还记录了使用代理 (与AspectJ编织相对) 时 ,开发人员不应失去的其他两个优点:
- 仅注释
public
方法。 带有其他可见性的注释方法将无济于事-的确没有任何意义-因为不会出现任何错误来警告您某些错误 - 警惕自我调用。 由于事务行为是基于代理的,因此即使目标对象的方法被标记为事务性,它的另一方法也不会导致事务行为。
通过将事务行为编织在字节码内而不是使用代理,可以消除这两个限制(但不是关于接口注释的第一个限制)。
您可以在此处以Eclipse / Maven格式找到本文的资源(但您必须配置MySQL数据库实例)。
翻译自: https://blog.frankel.ch/a-spring-hard-fact-about-transaction-management/