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
如果我将@Transactional
从TestService
移动到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);
参考:
<tx:advice/>
settings(弹簧参考)
Using @Transactional
(弹簧参考)
TransactionProxyFactorybean (javadoc)
【讨论】:
所以@Transactional 仅在您在接口的实现中使用它时才有效? 是的,除非您使用<tx:annotation-driven proxy-target-class="true" />
。然后CGLIB将用于创建动态子类
@seanizer:谢谢,所以我必须为每个服务类编写接口及其实现?我可以更改默认的@Transactional 机制吗?你说在 JDK 上工作但调试 s1 和 s2 我看到 TestService$$EnhancerByCGLIB$$$51486891 所以我认为它可以在 CGLIB 上工作,不是吗?
@seanizer:我现在阅读了您的评论,我现在只使用 ,mybew spring 3 默认使用 proxy-target-class="true"?跨度>
好的,那么也许公共领域是问题所在。尝试用一个私有字段和一个 getter 替换它,然后看看它是否有效。以上是关于spring 和@transactional,这正常吗?的主要内容,如果未能解决你的问题,请参考以下文章
Spring @Transactional 和 JDBC 自动提交