spring 和@transactional,这正常吗?

Posted

技术标签:

【中文标题】spring 和@transactional,这正常吗?【英文标题】:spring and @transactional, is this normal? 【发布时间】:2010-11-10 10:33:24 【问题描述】:

我写了这个简单的例子:

//file TestController.java
public interface TestController 

    public List<Test> findAll();



//file TestControllerImp.java
@Controller
public class TestControllerImp implements TestController

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) 
        this.sessionFactory=sessionFactory;
    

    public List<Test> findAll() 
        return sessionFactory.getCurrentSession().createQuery("from Test").list();
    



//file TestService.java
@Service
public class TestService 

    @Autowired
    private TestController controller;

    public boolean flag=true;

    public void setController(TestController controller)
        this.controller=controller;
    

    @Transactional
    public List<Test> useController()
        flag=false;
        return controller.findAll();
    


这是我的尝试:

TestService s1=context.getBean(TestService.class);
TestService s2=context.getBean(TestService.class);
List<Test> list=s1.useController();
System.out.println(s1.flag+"  "+s2.flag);

现在奇怪的行为(我对 spring 很陌生):

    如果我声明@Transactional 方法“useController()”,输出为:true true 如果我将@TransactionalTestService 移动到TestControllerImp,并用@Transactional 声明“findAll()”,则输出为:false false。

为什么我有这种行为?我知道默认情况下@Autowired 类是单音的,但为什么在第一种情况下标志仍然为真?

谢谢大家。

【问题讨论】:

【参考方案1】:

@Transactional 机制默认适用于 JDK 代理,并且仅适用于接口。

所以如果你让TestService 是一个接口,TestServiceImpl 是它的实现,那么上面的代码应该可以工作。

例如将类声明更改为:

@Service
public class TestServiceImpl implements TestService 

但测试代码必须引用接口,而不是类:

// this code remains unchanged
TestService s1=context.getBean(TestService.class);
TestService s2=context.getBean(TestService.class);

参考:

&lt;tx:advice/&gt; settings(弹簧参考) Using @Transactional(弹簧参考) TransactionProxyFactorybean (javadoc)

【讨论】:

所以@Transactional 仅在您在接口的实现中使用它时才有效? 是的,除非您使用&lt;tx:annotation-driven proxy-target-class="true" /&gt;。然后CGLIB将用于创建动态子类 @seanizer:谢谢,所以我必须为每个服务类编写接口及其实现?我可以更改默认的@Transactional 机制吗?你说在 JDK 上工作但调试 s1 和 s2 我看到 TestService$$EnhancerByCGLIB$$$51486891 所以我认为它可以在 CGLIB 上工作,不是吗? @seanizer:我现在阅读了您的评论,我现在只使用 ,mybew spring 3 默认使用 proxy-target-class="true"?跨度> 好的,那么也许公共领域是问题所在。尝试用一个私有字段和一个 getter 替换它,然后看看它是否有效。

以上是关于spring 和@transactional,这正常吗?的主要内容,如果未能解决你的问题,请参考以下文章

spring 和@transactional,这正常吗?

Spring @Transactional 和 JDBC 自动提交

Spring @Transactional 和 @Async

spring transaction注解原理

Spring @Transactional 使用

Spring Boot 和 Spring Data JPA @Transactional 不工作