0
点赞
收藏
分享

微信扫一扫

Spring中的多数据源和@Transactional事务配置

金刚豆 2023-04-05 阅读 83


基础Dao/Mapper定义

public interface BaseMapper {
	// read
	public Entity get(Integer id);
	
}

public interface JdbuyBaseMapper extends BaseMapper{

}

public interface LifecycleBaseMapper{

}


import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class MultiDataSource extends AbstractRoutingDataSource {

    public static void setDataSourceKey(String dataSource) {
    	MultiDataSourceHolder.setDataSource(dataSource);
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return MultiDataSourceHolder.getDataSource();
    }
}

多数据源AOP,动态切换数据源


/**
 * 多数据源AOP,动态切换数据源
 * 
 *
 */
@Aspect
public class MultiDataSourceAspectAdvice {

	private static final String JDBUY_DATA_SOURCE = "jdbuyDataSource";
	private static final String LIFECYCLE_DATA_SOURCE = "lifecycleDataSource";

	// @Pointcut("execution(* lifecycle.dao.*.*(..))")
	// 切入点路径配置很关键,dao包下的所有子包、所有类、所有方法,".."所有参数
	@Pointcut("execution(* lifecycle.dao.*.*.*(..))")
	protected void pointcut() {
	}

	// @Around("execution(* lifecycle.*.*(..))")
	@Around(value = "pointcut()")
	public Object doAround(ProceedingJoinPoint jp) throws Throwable {
		Object target = jp.getTarget();
		if (target instanceof LifecycleBaseMapper) {
			MultiDataSource.setDataSourceKey(LIFECYCLE_DATA_SOURCE);
		} else if (target instanceof JdbuyBaseMapper) {
			MultiDataSource.setDataSourceKey(JDBUY_DATA_SOURCE);
		}
		return jp.proceed();
	}
}


public class MultiDataSourceHolder {
	/**
	 * 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
	 */
	private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<String>();

	public static String getDataSource() {
		return dataSourceHolder.get();
	}

	public static void setDataSource(String dataSource) {
		dataSourceHolder.set(dataSource);
	}

	public static void clearDataSource() {
		dataSourceHolder.remove();
	}

}

普通的Mapper,不同的数据源继承不同的Mapper

@Repository
public interface BidProjectMapper extends JdbuyBaseMapper {

 //---------------------read-------------------------
 List<BidProject> listByProjectCodeList(@Param("projectCodeList")List<String> projectCodeList);


 //---------------------write-------------------------}
@Repository
public interface DataDictionaryMapper extends LifecycleBaseMapper {


 // ---------------------read-------------------------


 DataDictionary getBySourceId(@Param("sourceId") Integer sourceId, @Param("type") Integer type);
 // ---------------------write-------------------------
}

Spring多数据源和事务配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
	xmlns:task="http://www.springframework.org/schema/task" xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

	<!-- 多数据源,根据key动态切换 -->
	<bean id="lifecycleDataSource" class="com.alibaba.druid.pool.DruidDataSource"
		destroy-method="close">
		<!-- 数据库基本信息配置 -->
		<property name="driverClassName" value="${lifecycleDatasourceAsset.driverClassName}" />
		<property name="url" value="${lifecycleDatasourceAsset.url}" />
		<property name="username" value="${lifecycleDatasourceAsset.username}" />
		<property name="password" value="${lifecycleDatasourceAsset.password}" />
		<!-- 最大并发连接数 -->
		<property name="maxActive" value="${lifecycleDatasourceAsset.maxActive}" />
		<!-- 初始化连接数量 -->
		<property name="initialSize" value="${lifecycleDatasourceAsset.initialSize}" />
		<!-- 配置获取连接等待超时的时间 -->
		<property name="maxWait" value="${lifecycleDatasourceAsset.maxWait}" />
		<!-- 最小空闲连接数 -->
		<property name="minIdle" value="${lifecycleDatasourceAsset.minIdle}" />
		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
		<property name="timeBetweenEvictionRunsMillis"
			value="${lifecycleDatasourceAsset.timeBetweenEvictionRunsMillis}" />
		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
		<property name="minEvictableIdleTimeMillis"
			value="${lifecycleDatasourceAsset.minEvictableIdleTimeMillis}" />
		<property name="validationQuery" value="SELECT 1">
		</property>
		<!-- 打开removeAbandoned功能 -->
		<property name="removeAbandoned" value="true" />
		<!-- 1800秒,也就是30分钟 -->
		<property name="removeAbandonedTimeout" value="180" />
	</bean>
	
	<bean id="jdbuyDataSource" class="com.alibaba.druid.pool.DruidDataSource"
		destroy-method="close">
		<!-- 数据库基本信息配置 -->
		<property name="driverClassName" value="${jdbuyDatasourceAsset.driverClassName}" />
		<property name="url" value="${jdbuyDatasourceAsset.url}" />
		<property name="username" value="${jdbuyDatasourceAsset.username}" />
		<property name="password" value="${jdbuyDatasourceAsset.password}" />
		<!-- 最大并发连接数 -->
		<property name="maxActive" value="${jdbuyDatasourceAsset.maxActive}" />
		<!-- 初始化连接数量 -->
		<property name="initialSize" value="${jdbuyDatasourceAsset.initialSize}" />
		<!-- 配置获取连接等待超时的时间 -->
		<property name="maxWait" value="${jdbuyDatasourceAsset.maxWait}" />
		<!-- 最小空闲连接数 -->
		<property name="minIdle" value="${jdbuyDatasourceAsset.minIdle}" />
		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
		<property name="timeBetweenEvictionRunsMillis"
			value="${jdbuyDatasourceAsset.timeBetweenEvictionRunsMillis}" />
		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
		<property name="minEvictableIdleTimeMillis"
			value="${jdbuyDatasourceAsset.minEvictableIdleTimeMillis}" />
		<property name="validationQuery" value="SELECT 1">
		</property>
		<!-- 打开removeAbandoned功能 -->
		<property name="removeAbandoned" value="true" />
		<!-- 1800秒,也就是30分钟 -->
		<property name="removeAbandonedTimeout" value="180" />
	</bean>
	
	<bean id="multiDataSource" class="zc.lifecycle.dao.datasource.MultiDataSource">
        <property name="defaultTargetDataSource" ref="lifecycleDataSource"/>
        <property name="targetDataSources">
            <map>
                <entry key="jdbuyDataSource" value-ref="jdbuyDataSource"/>
                <entry key="lifecycleataSource" value-ref="lifecycleDataSource"/>
            </map>
        </property>
    </bean>
    
    <!-- 事务,每个数据源配置单独的事务 -->
	<bean name="lifecycleTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="lifecycleDataSource" />
		<qualifier value="lifecycle"/>  
	</bean>

	<tx:annotation-driven transaction-manager="lifecycleTransactionManager"
		proxy-target-class="true" />

	<bean name="jdbuyTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="jdbuyDataSource" />
		<qualifier value="jdbuy"/>  
	</bean>

	<!-- 注解事务 -->
	<tx:annotation-driven transaction-manager="jdbuyTransactionManager"
		proxy-target-class="true" />
		
	<!-- 配置mybatis -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="multiDataSource" />
		<property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
		<!-- mapper扫描 -->
		<property name="mapperLocations">
			<value>classpath:mybatis/mapper/**/*Mapper.xml</value>
		</property>
	</bean>

	<!--创建数据映射器,数据映射器必须为接口 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="annotationClass" value="org.springframework.stereotype.Repository" />
		<property name="basePackage" value="zc.lifecycle.dao" />
	</bean>

	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg ref="sqlSessionFactory" />
	</bean>
	<context:component-scan base-package="zc.lifecycle.dao" />
</beans>

选择使用某个事务

public class TaskCheckService {
	
	@Resource
	private TaskConfigMapper configMapper;
	
	//需要指定使用的事务标记,2个数据源
	@Transactional("lifecycle")
	public boolean startTask(String key,Long timeout) {
	
	}
}


举报

相关推荐

0 条评论