Multiple data sources are used in recently developed projects, and two rollback events with different transactions are used to ensure data consistency. Some of the code altogether refer to: MySQL as a case.
Configuration file
Spring.datasource.prod.driver-class-name=com.mysql.jdbc.driver
Spring.datasource.prod.url=jdbc:mysql://127.0.0.1:3306/test
Spring.datasource.prod.username=root
Spring.datasource.prod.password=root
Spring.datasource.dev.driver-class-name=com.mysql.jdbc.driver
Spring.datasource.dev.url=jdbc:mysql://127.0.0.1:3306/test1
Spring.datasource.dev.username=root
Spring.datasource.dev.password=root
Configure data sources and the management of transactions
Package com.lanwon.config;
Import java.sql.SQLException;
Import Javax.annotation.Resource;
Import Javax.sql.DataSource;
Import Org.apache.ibatis.session.SqlSessionFactory;
Import Org.mybatis.spring.SqlSessionFactoryBean;
Import Org.mybatis.spring.annotation.MapperScan;
Import Org.springframework.beans.factory.annotation.Qualifier;
Import Org.springframework.beans.factory.annotation.Value;
Import Org.springframework.context.annotation.Bean;
Import org.springframework.context.annotation.Configuration;
Import Org.springframework.context.annotation.Primary;
Import Org.springframework.core.io.support.PathMatchingResourcePatternResolver;
Import Org.springframework.core.io.support.ResourcePatternResolver;
Import Org.springframework.jdbc.datasource.DataSourceTransactionManager;
Import Com.alibaba.druid.pool.DruidDataSource;
/**
* @author DZB
* @date August 23, 2017
* Data Source Dev
*/
@Configuration # Different data sources should be layered when scanning DAO, otherwise you can only be bound once.
@MapperScan (basepackages= "Com.lanwon.mapper.dev", sqlsessionfactoryref= "Devsqlsessionfactory")
public class Devdatasourceconfig {
@Value ("${spring.datasource.dev.driver-class-name}")
Private String Dbdriver;
@Value ("${spring.datasource.dev.url}")
Private String Dburl;
@Value ("${spring.datasource.dev.username}")
Private String UserName;
@Value ("${spring.datasource.dev.password}")
private String password;
@Resource
Private Globaldbconfig Globaldbconfig;
private static final String Mapper_path = "Classpath*:/mapper/dev/*.xml";
private static final String entity_package = "Com.lanwon.entity.dev";
@Bean (name = "Devdatasource")
@Primary
Public DataSource Devdatasource () throws SQLException {
Druiddatasource DataSource = new Druiddatasource ();
Datasource.setdriverclassname (Dbdriver);
Datasource.seturl (Dburl);
Datasource.setusername (UserName);
Datasource.setpassword (password);
Datasource.setfilters (Globaldbconfig.getdbfilters ());
Datasource.setmaxactive (Globaldbconfig.getdbmaxactive ());
Datasource.setmaxwait (Globaldbconfig.getdbmaxwait ());
Datasource.setminidle (Globaldbconfig.getdbminidle ());
Datasource.settimebetweenevictionrunsmillis (globaldbconfig
. Getdbtimebetweenevictionrunsmillis ());
Datasource.setminevictableidletimemillis (globaldbconfig
. Getdbminevictableidletimemillis ());
Datasource.settestwhileidle (Globaldbconfig.isdbtestwhileidle ());
Datasource.setvalidationquery (Globaldbconfig.getdbvalidationquery ());
Datasource.settestonborrow (Globaldbconfig.isdbtestonborrow ());
Datasource.settestonreturn (Globaldbconfig.isdbtestonreturn ());
Datasource.setpoolpreparedstatements (globaldbconfig
. isdbpoolpreparedstatements ());
Datasource.setmaxopenpreparedstatements (globaldbconfig
. getdbmaxopenpreparedstatements ());
Datasource.init ();
return dataSource;
}
@Bean (name = "Devtransactionmanager")
@Primary
Public Datasourcetransactionmanager Devtransactionmanager ()
Throws SQLException {
return new Datasourcetransactionmanager (Devdatasource ());
}
@Bean (name = "Devsqlsessionfactory")
@Primary//default
Public Sqlsessionfactory Devsqlsessionfactory (
@Qualifier ("Devdatasource") DataSource Ddatasource)
Throws Exception {
Final Sqlsessionfactorybean sessionfactory = new Sqlsessionfactorybean ();
Sessionfactory.setdatasource (Ddatasource);
Resourcepatternresolver resolver = new Pathmatchingresourcepatternresolver ();
Sessionfactory.setmapperlocations (Resolver.getresources (Mapper_path));
Sessionfactory.settypealiasespackage (Entity_package);
return Sessionfactory.getobject ();
}
}
Import java.sql.SQLException;
Import Javax.annotation.Resource;
Import Javax.sql.DataSource;
Import Org.apache.ibatis.session.SqlSessionFactory;
Import Org.mybatis.spring.SqlSessionFactoryBean;
Import Org.mybatis.spring.annotation.MapperScan;
Import Org.springframework.beans.factory.annotation.Qualifier;
Import Org.springframework.beans.factory.annotation.Value;
Import Org.springframework.context.annotation.Bean;
Import org.springframework.context.annotation.Configuration;
Import Org.springframework.context.annotation.Primary;
Import Org.springframework.core.io.support.PathMatchingResourcePatternResolver;
Import Org.springframework.core.io.support.ResourcePatternResolver;
Import Org.springframework.jdbc.datasource.DataSourceTransactionManager;
Import Com.alibaba.druid.pool.DruidDataSource;
/**
* @author DZB
* @date August 23, 2017
* Data Source Prod
*/
@Configuration
@MapperScan (basepackages= "Com.lanwon.mapper.prod", sqlsessionfactoryref= "Prodsqlsessionfactory")
public class Proddatasourcesconfig {
@Value ("${spring.datasource.prod.driver-class-name}")
Private String Dbdriver;
@Value ("${spring.datasource.prod.url}")
Private String Dburl;
@Value ("${spring.datasource.prod.username}")
Private String UserName;
@Value ("${spring.datasource.prod.password}")
private String password;
@Resource
Private Globaldbconfig Globaldbconfig;
private static final String Mapper_path = "Classpath*:/mapper/prod/*.xml";
private static final String entity_package = "Com.lanwon.entity.prod";
@Bean (name = "Proddatasource")
Public DataSource Proddatasource () throws SQLException {
Druiddatasource DataSource = new Druiddatasource ();
Datasource.setdriverclassname (Dbdriver);
Datasource.seturl (Dburl);
Datasource.setusername (UserName);
Datasource.setpassword (password);
Datasource.setfilters (Globaldbconfig.getdbfilters ());
Datasource.setmaxactive (Globaldbconfig.getdbmaxactive ());
Datasource.setmaxwait (Globaldbconfig.getdbmaxwait ());
Datasource.setminidle (Globaldbconfig.getdbminidle ());
Datasource.settimebetweenevictionrunsmillis (globaldbconfig
. Getdbtimebetweenevictionrunsmillis ());
Datasource.setminevictableidletimemillis (globaldbconfig
. Getdbminevictableidletimemillis ());
Datasource.settestwhileidle (Globaldbconfig.isdbtestwhileidle ());
Datasource.setvalidationquery (Globaldbconfig.getdbvalidationquery ());
Datasource.settestonborrow (Globaldbconfig.isdbtestonborrow ());
Datasource.settestonreturn (Globaldbconfig.isdbtestonreturn ());
Datasource.setpoolpreparedstatements (globaldbconfig
. isdbpoolpreparedstatements ());
Datasource.setmaxopenpreparedstatements (globaldbconfig
. getdbmaxopenpreparedstatements ());
Datasource.init ();
return dataSource;
}
@Bean (name = "Prodtransactionmanager")
Public Datasourcetransactionmanager Prodtransactionmanager ()
Throws SQLException {
return new Datasourcetransactionmanager (Proddatasource ());
}
@Bean (name = "Prodsqlsessionfactory")
Public Sqlsessionfactory Prodsqlsessionfactory (
@Qualifier ("Proddatasource") DataSource Pdatasource)
Throws Exception {
Final Sqlsessionfactorybean sessionfactory = new Sqlsessionfactorybean ();
Sessionfactory.setdatasource (Pdatasource);
Resourcepatternresolver resolver = new Pathmatchingresourcepatternresolver ();
Sessionfactory.setmapperlocations (Resolver.getresources (Mapper_path));
Sessionfactory.settypealiasespackage (Entity_package);
return Sessionfactory.getobject ();
}
}
Using the transaction manager
You only need to add a note @transactional in a method that requires a transaction and specify its value. Similarly, value values match the corresponding transaction management method name.
/**
* @author DZB
* @since 2016/7/5-22:21
*/
@Service
public class Userdetailserviceimpl implements Userdetailservice {
@Autowired
Private Userdetailmapper Userdetailmapper;
Public list<userdetail> Selectuserdetail () {
return Userdetailmapper.selectall ();
}
@Transactional (value= "Devtransactionmanager")
@Override
public int update (Userdetail userdetail) {
int b=userdetailmapper.update (userdetail);
return b;
}
}
@Service
public class Userinfoserviceimpl implements Userinfoservice {
@Autowired
Private Userinfomapper Userinfomapper;
@Autowired
Private Userdetailserviceimpl Detailserviceimpl;
Public list<userinfo> Selectuserinfo () {
return Userinfomapper.selectall ();
}
@Transactional (value= "Prodtransactionmanager")
@Override
public int update (UserInfo UserInfo) {
int a =userinfomapper.update (userInfo);
return A;
}
@Transactional (value= "Prodtransactionmanager")
@Override
public int update (String name1,string name2) {
int c=0;
UserInfo info = new UserInfo ();
Info.setid ("1");
Info.setusername (NAME1);
int b=userinfomapper.update (info);
if (b>0) {
Userdetail detail = new Userdetail ();
Detail.setid (1L);
Detail.setname (name2);
C=detailserviceimpl.update (detail);
}
return C;
}
}
Types of transactional propagation behavior
Spring provides 7 types of transactional propagation behavior in the Transactiondefinition interface.
They specify how transactions propagate when the transaction method and transaction method occur when nested calls are made:
Table 1 Transactional propagation behavior types
Transactional propagation behavior Type
Description
Propagation_required
If there is currently no transaction, create a new transaction, if there is already a transaction, join in the transaction. This is the most common choice.
Propagation_supports
Supports the current transaction, which is performed in a non transactional manner if there are currently no transactions.
Propagation_mandatory
Uses the current transaction and throws an exception if there are currently no transactions.
Propagation_requires_new
Creates a new transaction and suspends the current transaction if there is currently a transaction.
propagation_not_supported
Performs an operation in a non transactional manner, suspending the current transaction if there is currently a transaction.
Propagation_never
Executes in a non transactional manner and throws an exception if there is a current transaction.
propagation_nested
Executes within a nested transaction if there is currently a transaction. If there is currently no transaction, a similar operation is performed with Propagation_required.
Note: This article is my own experience of writing, if there is not very right place, please advise.
Project Source Github:https://github.com/sdmxdzb/transcations