【问题标题】:spring and @transactional, is this normal?spring 和@transactional,这正常吗?
【发布时间】: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 很陌生):

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

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

谢谢大家。

【问题讨论】:

    标签: java hibernate spring transactional


    【解决方案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);
    

    参考:

    【讨论】:

    • 所以@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 替换它,然后看看它是否有效。
    猜你喜欢
    • 1970-01-01
    • 2023-03-10
    • 2012-06-22
    • 2019-06-30
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多