Spring @Transactional 包装 2 种方法
Posted
技术标签:
【中文标题】Spring @Transactional 包装 2 种方法【英文标题】:Spring @Transactional wrapping 2 methods 【发布时间】:2011-03-31 10:31:13 【问题描述】:我是春季新手。我对我的 dao 方法使用 @Transactional 注释:
@Transactional
public Person getById(long id)
return new Person(jdbcTemplate.queryForMap(...));
@Transactional
public void save(Person person)
jdbcTemplate.update(...);
我已经这样设置了事务管理器:
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
问题是当我的客户端代码调用dao.save(..)
然后dao.getById(4)
这些发生在两个单独的事务中。如何将这两个调用包装在同一个数据库事务中?最好不要以编程方式进行。
谢谢
【问题讨论】:
【参考方案1】:将事务属性放在 DAO 层是不好的做法。另外,我不确定您为什么需要 getById 方法的事务。即使您想使用事务,您也需要将传播行为指定为 REQUIRES_NEW 用于保存和 getById 方法。
【讨论】:
【参考方案2】:@Transactional(propagation = REQUIRES_NEW, readOnly = false)
public Person saveAndGetById(Person person, long id)
save(person);
return getById(id);
@Transactional(propagation = REQUIRED)
public Person getById(long id)
return new Person(jdbcTemplate.queryForMap(...));
@Transactional(propagation = REQUIRED, readOnly = false)
public void save(Person person)
jdbcTemplate.update(...);
然而,最好的办法是让“save”方法返回一个 ID,因为事先很难知道 Person 将保留哪个 ID。
【讨论】:
谢谢。 getById 只是一个例子。【参考方案3】:在这种情况下,好的做法是将调用这两种 DAO 方法的服务方法标记为@Transactional
。此案已明确讨论here。
【讨论】:
以上是关于Spring @Transactional 包装 2 种方法的主要内容,如果未能解决你的问题,请参考以下文章
Grails @Transactional 与 Spring @Transactional 注释之间的差异