事务管理器配置
// 分布式事务管理器
@Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
public TransactionManager atomikosTransactionManager() throws Throwable {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(false);
return userTransactionManager;
}
/**
* 注入事物管理器
*
* @return
* @throws Throwable
*/
@Bean(name = "xatx")
@DependsOn({ "userTransaction", "atomikosTransactionManager" })
public JtaTransactionManager regTransactionManager() throws Throwable {
TransactionManager userTransactionManager = atomikosTransactionManager();
UserTransaction userTransaction = userTransaction();
return new JtaTransactionManager(userTransaction, userTransactionManager);
}
@Bean(name = "userTransaction")
public UserTransaction userTransaction() throws Throwable {
UserTransactionImp userTransactionImp = new UserTransactionImp();
userTransactionImp.setTransactionTimeout(10000);
return userTransactionImp;
}
//目前业务只有BIZ需要事务
@Bean(name = "bizTransaction")
@Primary
public PlatformTransactionManager bizTransaction(@Qualifier(value = "bizDataSource") DataSource dataSource) {
DataSourceTransactionManager manager = new DataSourceTransactionManager();
manager.setDataSource(dataSource);
return manager;
}
配置dataSource(需要配置XA事务的数据源需要配置两个,一个XA数据源和一个非XA事务的数据源)
@Bean(name = "tempDataSource")
@Autowired
public DataSource systemDataSource(Environment env) {
DruidDataSource ds = new DruidDataSource();
build(env, "spring.datasource.druid.temp.",ds);
return ds;
}
@Autowired
@Bean(name = "bizDataSource")
@Primary
public DataSource businessDataSource(Environment env) {
DruidDataSource ds = new DruidDataSource();
build(env, "spring.datasource.druid.biz.",ds);
return ds;
}
@Autowired
@Bean(name = "bizXADataSource")
@DependsOn({"xatx"})
public AtomikosDataSourceBean bizXADataSource(Environment env) {
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
DmdbXADataSource datasource;
String prefix = "spring.datasource.druid.biz.";
try {
datasource = new DmdbXADataSource();
datasource.setURL(env.getProperty(prefix + "url"));
datasource.setPassword(env.getProperty(prefix + "password"));
datasource.setUser(env.getProperty(prefix + "username"));
ds.setXaDataSource(datasource);
} catch (SQLException e) {
e.printStackTrace();
}
ds.setUniqueResourceName("bizDB");
ds.setMinPoolSize(0);
ds.setMaintenanceInterval(600);
ds.setTestQuery("select 2");
return ds;
}
@Autowired
@Bean(name = "internetDataSource")
public DataSource internetDataSource(Environment env) {
DruidDataSource ds = new DruidDataSource();
build(env, "spring.datasource.druid.internetdb.",ds);
return ds;
}
@Autowired
@Bean(name = "internetXADataSource")
@DependsOn({"xatx"})
public AtomikosDataSourceBean internetXADataSource(Environment env) {
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
Properties prop = build(env, "spring.datasource.druid.internetdb.");
ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
ds.setUniqueResourceName("internetDB");
ds.setMinPoolSize(0);
ds.setXaProperties(prop);
ds.setMaintenanceInterval(600);
ds.setMaxLifetime(20000);
ds.setTestQuery("select 2");
return ds;
}
配置sessionFactroy(XA事务和非XA事务要分包,并且不能混合使用,通过basePackages 来区分dataSource)
package com.neusoft.saca.hlwjjg.config;
import javax.sql.DataSource;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
@Configuration
@MapperScan(basePackages = "com.neusoft.saca.hlwjjg.biz.**.mapper", sqlSessionFactoryRef = "bizSqlSessionFactory",
nameGenerator = MultidataApplication.SpringBeanNameGenerator.class)
public class BizDataSourceConfiguration {
public static final Logger LOGGER = LoggerFactory.getLogger(BizDataSourceConfiguration.class);
@Autowired
@Qualifier("bizDataSource")
private DataSource ds;
// @Resource
// private TraceSQL traceSQL;
@Bean
public SqlSessionFactory bizSqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(ds);
//指定mapper xml目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factoryBean.setPlugins(new PaginationInterceptor[]{new PaginationInterceptor()});
factoryBean.setMapperLocations(resolver.getResources("classpath:mapper/biz/**/*.xml"));
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate bizSqlSessionTemplate() throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(bizSqlSessionFactory()); // 使用上面配置的Factory
return template;
}
@Bean
public SqlSessionTemplate bizBatchSqlSession() throws Exception {
return new SqlSessionTemplate(bizSqlSessionFactory(), ExecutorType.BATCH);
}
}
配置非XA事务切面
package com.neusoft.saca.hlwjjg.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import com.neusoft.saca.hlwjjg.exception.BusinessException;
@Aspect
@Configuration
public class TransactionAdviceConfig {
private static final String AOP_POINTCUT_EXPRESSION_BIZ = "execution (* com.neusoft.saca.hlwjjg.biz.**.service..*.*(..))";
@Resource(name = "bizTransaction")
private PlatformTransactionManager bizManager;
private static final int TX_METHOD_TIMEOUT=5;
@Bean(name="txbizAdvice")
public TransactionInterceptor txbizAdvice() {
/*事务管理规则,声明具备事务管理的方法名*/
NameMatchTransactionAttributeSource source=new NameMatchTransactionAttributeSource();
/*只读事物、不做更新删除等*/
/*当前存在事务就用当前的事务,当前不存在事务就创建一个新的事务*/
RuleBasedTransactionAttribute readOnlyRule=new RuleBasedTransactionAttribute();
/*设置当前事务是否为只读事务,true为只读*/
readOnlyRule.setReadOnly(true);
/* transactiondefinition 定义事务的隔离级别;
* PROPAGATION_NOT_SUPPORTED支持当前事务,如果没有事务的话以非事务方式执行*/
readOnlyRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
RuleBasedTransactionAttribute requireRule=new RuleBasedTransactionAttribute();
/*抛出异常后执行切点回滚*/
List<RollbackRuleAttribute> exceptions = new ArrayList<>();
exceptions.add(new RollbackRuleAttribute(Exception.class));
exceptions.add(new RollbackRuleAttribute(BusinessException.class));
requireRule.setRollbackRules(exceptions);
/*PROPAGATION_REQUIRED:事务隔离性为1,若当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。 */
requireRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
/*设置事务失效时间,如果超过5秒,则回滚事务*/
requireRule.setTimeout(TX_METHOD_TIMEOUT);
Map<String,TransactionAttribute> txMap=new HashMap<>();
txMap.put("add*",requireRule);
txMap.put("save*", requireRule);
txMap.put("saveOrUpdate*", requireRule);
txMap.put("insert*",requireRule);
txMap.put("update*",requireRule);
txMap.put("delete*",requireRule);
txMap.put("remove*",requireRule);
txMap.put("get*",readOnlyRule);
txMap.put("check*",readOnlyRule);
txMap.put("query*", readOnlyRule);
txMap.put("find*", readOnlyRule);
txMap.put("select*",readOnlyRule);
txMap.put("list*",readOnlyRule);
source.setNameMap(txMap);
TransactionInterceptor txAdvice=new TransactionInterceptor(bizManager, source);
return txAdvice;
}
@Bean(name="txbizAdviceAdvisor")
public Advisor txAdviceAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_POINTCUT_EXPRESSION_BIZ);
return new DefaultPointcutAdvisor(pointcut, txbizAdvice());
}
}