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

标签 java mysql spring transactions spring-transactions

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

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

两个数据源:

<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 注释吗?它会像任何其他方法调用一样运行吗?

我已经阅读了引用资料和各种在线帖子,但我仍然不确定这种行为。

最佳答案

Is it safe ?

没有。 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
    }
}

关于java - 只有一个事务数据源的 Spring @Transactional 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35524879/

相关文章:

java - Spring webapp - 在应用程序停止时关闭线程

java - 使用 Spring MVC 向用户呈现服务级别验证错误的良好实践

java - 如何设置 setContentView();去

java - Spring 3.2/hibernate 4.1.9 : Use of @OneToMany or @ManyToMany targeting an unmapped class error

java - 如何触发 MINA 客户端消息事件?

mysql - 如何根据条件比较同一表中的行

java - 为单元测试中的 @Value 字段提供上下文

java - DateUtils 无法解析

mysql - 当返回的行数无关紧要时,在子查询上设置 LIMIT

php - 从 MySQL 查询结果创建关联数组 - PHP