春天和@transactional,这是正常的吗?

时间:2010-11-10 10:33:25

标签: java hibernate spring transactional

我写了这个简单的例子:

//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);

现在这种奇怪的行为(我对春天很新):

  1. 如果我声明@Transactional方法“useController()”,则输出为:true true
  2. 如果我将@TransactionalTestService移至TestControllerImp,并使用@Transactional声明“findAll()”,则输出为:false false。
  3. 为什么我有这种行为?我知道默认@Autowired类是单音,但为什么在第一种情况下标志仍然是真的?

    谢谢大家。

1 个答案:

答案 0 :(得分:5)

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

因此,如果您让TestService成为接口并且TestServiceImpl是其实现,那么上述代码应该可以正常工作。

e.g。将类声明更改为:

@Service
public class TestServiceImpl implements TestService {

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

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

参考: