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 种方法的主要内容,如果未能解决你的问题,请参考以下文章

关于服务和@Transactional

spring aop获取代理目标对象

Grails @Transactional 与 Spring @Transactional 注释之间的差异

Spring @Transactional 和 Spring @Lock 注解有啥关系?

Spring @Transactional 使用

Spring @Transactional 只读传播