【发布时间】:2019-03-27 23:16:49
【问题描述】:
关于@Transactional,我有 2 个问题无法为他们解答:
1- 界面上的@Transnational
根据答案:
如果您将应用设置为 proxy-target-class='true'(在您的应用上下文中,如果您对接口进行注释,则不会获取您的 @Transactional 信息。
我将 application.properties 配置为:
spring.aop.proxy-target-class=true
并且界面上的注释仍然被选中,我还尝试了以下方法(EnableTransacationManagement 上的proxyTargetClass = true):
@SpringBootApplication
@EnableAsync
@EnableTransactionManagement(proxyTargetClass = true)
public class Application extends SpringBootServletInitializer {
}
@Transnational 仍然在我只在 interface 上配置的地方工作,所以我在这里缺少什么?
2- @Transnational 有@Inherited,@inherited 根据 java 文档:
请注意,如果注释类型用于注释类以外的任何内容,则此元注释类型无效。另请注意,此元注释仅导致注释从超类继承;已实现接口上的注释无效。
我有以下用@Transnational 注释的接口,它仍在处理扩展它的接口:
@Repository
@Transactional
public interface UserRepository extends JpaRepository<User, Long> {
}
以下/下面的接口有修改查询,如果没有@Transactional,它将无法工作,我已经用@Transacational 注释了上面的接口并且它正在被拾取(如果我在父方法而不是类上配置它甚至可以工作):
public interface TestRepository extends UserRepository {
@Query("UPDATE User U set U.name='hello' where U.id=1")
@Modifying
public void test();
}
如果@Inherited 对接口没有影响,那么事务如何工作?
更新:问题 1
我什至在接口方法上尝试了@Async,它在没有注释实现类的情况下工作,AOP 正在使用 CGLIB 代理(仅在注释接口方法时)这与大多数不确定是否有问题的答案相矛盾。
【问题讨论】:
-
@Transactional和@Async工作是因为 Spring,在这些情况下,还会扫描由类实现的接口以查找该注释。这是 Spring 中的一个特性,与注解是否为@Inherited无关。虽然,恕我直言,您不应该将这些注释放在接口上,因为它们属于类。这些行为应该是实现细节。最后,您在引用常规 Spring 参考指南时使用了 Spring Data JPA。 Spring Data JPA 有另一种检测@Transactional等的方法。 -
@M.Deinum 代理目标类呢?如果我们不使用JDK代理,接口上的注释不应该被忽略吗?如果注释只设置在接口方法上,那么为什么 CGLIB 不忽略它
-
因为不管它是如何代理的,Spring会检测实现的接口,如果在实现类上找不到,就会扫描那些。
-
@M.Deinum 那么这里的第二个答案不正确?stackoverflow.com/questions/5551541/…)。 ?它有 40 票,上面写着 If you have your app set to proxy-target-class='true' (在您的应用程序上下文中,如果您对接口进行注释,则不会获取您的事务信息。
-
该答案不适用于此处,因为您使用的是 Spring Data JPA……该答案适用于基于 Spring 的常规 bean 和 IIRC,其行为已更改,并且无论如何都会在接口上检测到该信息。跨度>
标签: java spring spring-boot transactional