Spring 多數據源 @Transactional 註解事務管理

在 Spring,MyBatis 下兩個數據源,通過 @Transactional 註解 配置簡單的事務管理

spring-mybatis.xml

<!--******************************** data one start ***************************************************************-->
<!-- 數據庫連接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
   <property name="driverClassName" value="${jdbc.driver}" />
   <property name="url" value="${jdbc.url}" />
   <property name="username" value="${jdbc.username}" />
   <property name="password" value="${jdbc.password}" />
   <property name="initialSize" value="10" />
   <property name="minIdle" value="50" />
   <property name="maxActive" value="100" />
   <property name="maxWait" value="60000" />
   <property name="useUnfairLock" value="true" />
   <property name="timeBetweenEvictionRunsMillis" value="300000" />
   <property name="minEvictableIdleTimeMillis" value="600000" />
   <property name="validationQuery" value="select 1" />
   <property name="testWhileIdle" value="true" />
   <property name="testOnBorrow" value="true" />
   <property name="poolPreparedStatements" value="true" />
   <property name="maxOpenPreparedStatements" value="200" />
   <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
</bean>

<!-- 讓spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
   <!-- 數據庫連接池 -->
   <property name="dataSource" ref="dataSource" />
   <!-- 加載mybatis的全局配置文件 -->
   <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
   <!-- 自動掃描mapping.xml文件 -->
       <property name="mapperLocations" value="classpath:mybatis/mapping/*.xml" />
</bean>

<!-- DAO接口所在包名,Spring會自動查找其下的類 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
   <property name="basePackage" value="com.***.***.dao" />
   <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>

<!-- 設定transactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <property name="dataSource" ref="dataSource" />
</bean>
<!-- 支持 @Transactional 標記 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<!--******************************** data one end ***************************************************************-->


<!--******************************** data two start ***************************************************************-->
<!-- 數據庫連接池 -->
<bean id="dataSourceTwo" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
   <!--略寫-->
</bean>

<!-- 讓spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
<bean id="sqlSessionFactoryTwo" class="org.mybatis.spring.SqlSessionFactoryBean">
   <property name="dataSource" ref="dataSourceTwo" />
   <!--略寫-->
</bean>

<!-- DAO接口所在包名,Spring會自動查找其下的類 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
   <!--略寫-->
   <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryTwo" />
</bean>

<!-- 設定transactionManager -->
<bean id="transactionManagerTwo" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <property name="dataSource" ref="dataSourceTwo" />
</bean>
<!-- 支持 @Transactional 標記 -->
<tx:annotation-driven transaction-manager="transactionManagerTwo" proxy-target-class="true" />
<!--******************************** data two end 略寫 ***************************************************************-->

上面配置了兩個數據源(dataSource,dataSourceTwo),兩個事務管理器(transactionManager,transactionManagerTwo)

@Transactional 事務註解

1)第一個數據源,使用第一個事務管理器

@Override
@Transactional(value = "transactionManager",readOnly = false)
public void insert {
}

2)第二個數據源,使用第二個事務管理器

@Override
@Transactional(value = "transactionManagerTwo",readOnly = false)
public void insert {
}

3)不使用 value 或者 @Transactional 標記,會使用 哪個數據源 及起哪個事務?

@Override
@Transactional
public void insert {
}
@Override
public void insert {
}
像這種不標明的情況,會使用默認 事務管理器(transactionManager),所以只有一個事務管理器的時候,我們一般不寫 value


引出:一條SQL語句是否需要事務

事務的存在意義:當我們在執行數據庫操作時,例如:insert,update,delete  ,當發生錯誤導致執行失敗時,我們需要對整個操作進行回滾。

當我們只有一個操作如 insert,我們是不需要搞個事務跟蹤的, 因爲一條語句就是一個事務,它自己本身就已經有事務了!!!

就算這條 insert 語句執行失敗,它自然不會插入成功,同時也不會對其它操作造成影響。

按我理解,事務應該用在執行多條語句,並且語句之間會相互影響的時候才需要,事務是用在多個語句保證同時成功的時候用,單個語句不建議用


需要注意的是,多個數據庫的這種配置是不支持分佈式事務的,也就是同一個事務中,不能操作多個數據庫。

如果要實現分佈式事務可參考:

Spring分佈式事務實現

spring多數據源配置

Spring, MyBatis 多數據源的配置和管理

關注公衆號,分享乾貨,討論技術

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章