Spring只有一个事务数据源的@Transactional行为

时间:2016-02-20 14:54:10

标签: java mysql spring transactions spring-transactions

我有一个访问两个数据库的应用程序。显然,如果我需要跨两个DB的事务,我需要使用两阶段提交之类的东西。但我现在不需要这个保证之王,我不需要一切都是交易的。事情可能会崩溃或独立成功,应用程序可以处理它,而不是最终处于不一致状态。

现在我有一个像这样的设置(删除接口,代码等,以使其尽可能简单地解释):

两个数据来源:

<bean id="firstDS" class="org.springframework.jndi.JndiObjectFactoryBean">
    <qualifier value="firstDS" />
    <property name="jndiName" value="java:comp/env/jdbc/firstDS" />
</bean>

<bean id="secondDS" class="org.springframework.jndi.JndiObjectFactoryBean">
    <qualifier value="secondDS" />
    <property name="jndiName" value="java:comp/env/jdbc/secondDS" />
</bean>

只有一个数据源的一个事务管理器:

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="firstDS" />
</bean>

服务:

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class Service {

    @Autowired
    private FirstDao firstDao;

    @Autowired
    private SecondDao secondDao;

    public void updateStuff() {
        firstDao.updateStuff();
        secondDao.updateStuff();
    }
}

和两个DAO:

@Transactional(propagation = Propagation.MANDATORY)
public class FirstDao {

    @Autowired
    @Qualifier("firstDS")
    private DataSource dataSource;

    public void updateStuff() {
        // updates stuff in the first database using dataSource
    }
}

@Transactional(propagation = Propagation.MANDATORY)
public class SecondDao {

    @Autowired
    @Qualifier("secondDS")
    private DataSource dataSource;

    public void updateStuff() {
        // updates stuff in the second database using dataSource
    }
}

现在,这没有问题(或至少没有我能观察到的),但我的问题是:

  • 这是安全的还是有副作用?
  • 第二个DAO是如何处理的,因为它是事务性的,但事务是针对另一个数据库的?
  • 我应该从第二个DAO中删除@Transactional注释吗?它会像其他任何方法调用那样表现吗?

我已经在线阅读了参考文献和各种帖子,但我仍然不确定这种行为。

1 个答案:

答案 0 :(得分:1)

  

安全吗?

没有。 SecondDao.updateStuff将在没有逻辑事务的情况下执行。这意味着在SecondDao.updateStuff期间执行的每个查询都将在自动提交模式下以单独的物理事务执行。换句话说:SecondDao.updateStuff不是事务性的(甚至可能为每个查询使用一个单独的连接......这可能导致性能问题)。

你能做什么?

首先为您的secondDS声明一个transactionManager:

<tx:annotation-driven/>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="firstDS" />
</bean>
<bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="secondDS" />
</bean>

然后指定SecondDAO使用transactionManger2:

@Transactional(value="transactionManager2",propagation = Propagation.REQUIRED)
public class SecondDao {

    @Autowired
    @Qualifier("secondDS")
    private DataSource dataSource;

    public void updateStuff() {
        // updates stuff in the second database using dataSource
    }
}