spring 和@transactional,这正常吗?

发布于 2024-10-01 17:05:30 字数 1532 浏览 5 评论 0原文

我写了这个简单的例子:

//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()”,输出是:假假。

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

谢谢大家。

i wrote this simple example:

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

}

And this is my try:

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

Now the strange behaviour (im very new with spring):

  1. If i declare @Transactional the method "useController()", the output is: true true
  2. If i move @Transactional from TestService to TestControllerImp, and i declare "findAll()" with @Transactional, the output is: false false.

Why i have this behaviour? I know by default @Autowired classes are singletone, but why in the first case the flag still remains true?

Thanks all.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

十六岁半 2024-10-08 17:05:31

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

参考:

The @Transactional mechanism works on JDK proxies per default and those work on interfaces only.

So if you let TestService be an interface and TestServiceImpl be its implementation, then the above code should work.

e.g. change the class declaration to this:

@Service
public class TestServiceImpl implements TestService {

but the test code must reference the interface, not the class:

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

Reference:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文