Spring-boot项目中动态切换数据源,多数据源切换,定时的数据跟新,千万数据级别的。
1.首先是切换数据源,我用华丽的手法打开了百度,面对百度编程,学习就像呼吸一样自然动态切换我使用的数据源信息配置在xml中,适用于一般数据库切换。执行完某操作,切换数据库,执行另一个操作。(项目比较还是 ssm框架的,到时候我研究下 会发布一个springboot 的版本的)
1…继承AbstractRoutingDataSource,重写determineCurrentLookupKey方法
2… 配置xml,这里将上面创建的DynamicDataSource注入到spring容器中,这里主要用到AbstractRoutingDataSource的两个属性defaultTargetDataSource和targetDataSources。defaultTargetDataSource默认目标数据源,targetDataSources(map类型)存放用来切换的数据源。配置完以后,其他地方用到数据源的话,都引用DynamicDataSource,配置两个不一样的数据源(这里我也不知道为什么公司配置的mybatis配置文件,吐槽单纯的脑瘫,整理在一起不好)
<beans profile="production"> <!-- 数据源配置, 使用 BoneCP 数据库连接池 --> <bean id="dataSourceA" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass --> <property name="driverClassName" value="${jdbc.driver}" /> <!-- 基本属性 url、user、password --> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="${jdbc.pool.minIdle}" /> <property name="minIdle" value="${jdbc.pool.minIdle}" /> <property name="maxActive" value="${jdbc.pool.maxActive}" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="60000" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="SELECT 'x' from dual" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用) --> <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> <!-- 配置监控统计拦截的filters <property name="filters" value="stat,wall" /> --> </bean> <!-- 多数据源配置 --> <bean id="dataSourceB" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="${jdbc1.driver}" /> <property name="url" value="${jdbc1.url}" /> <property name="username" value="${jdbc1.username}" /> <property name="password" value="${jdbc1.password}" /> <property name="initialSize" value="${jdbc1.pool.minIdle}" /> <property name="minIdle" value="${jdbc1.pool.minIdle}" /> <property name="maxActive" value="${jdbc1.pool.maxActive}" /> <property name="maxWait" value="60000" /> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="SELECT 'x' from dual" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> </bean>
<!-- MyBatis begin --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dynamicDataSource"/> <!--<property name="dataSource" ref="dataSourceA"/>--> <property name="typeAliasesPackage" value="com.fjca.frame"/> <property name="typeAliasesSuperType" value="com.fjca.frame.common.persistence.BaseEntity"/> <property name="mapperLocations" value="classpath:/mappings/${jdbc.type}/**/*.xml"/> <property name="configLocation" value="classpath:/mybatis-config.xml"></property> </bean> 3…手动切换数据源,切换完以后,记得再切回默认数据库。
ok 成功
多数据源ok ,(本来想的在数据库配置动态的数据源的。刚提出实现方法,就被领导催赶进度,后面有空再弄)接下来是定时任务,还有切换数据的时候跟事务会有冲突,当时差点把头发都薅秃噜皮了。看了源码,跟aop有关系,大佬解释如下:
开启事务的同时,会从数据库连接池获取数据库连接;如果内层的service使用@DS切换数据源,只是又做了一层拦截,但是并没有改变整个事务的连接;在这个事务内的所有数据库操作,都是在事务连接建立之后,所以会产生数据源没有切换的问题;为了使@DS起作用,必须替换数据库连接,也就是改变事务的传播机智,产生新的事务,获取新的数据库连接;所以Service的save方法上除了加@Transactional外,还需要设置propagation = Propagation.REQUIRES_NEW(Mybatis plus的多数据源@DS切换为什么不起作用了,谁的锅,@Transactional_Meiko记录-CSDN博客)
2.写代码就是像人生,有些人出生就会coding,有些人生来就是warning。比如我就属于选择困难症(quartz与Scheduler)。 调度任务已经是写的如火纯情了,首先启动调度任务。写好自己自己要定时调用的时间和定时调用的类即可,那些我都存在数据库里面.
2.在启动调动的的任务类的时候,在spring的容器里面大部分的类都没有初始化所以就只能使用映射的方式自己NEW了,类似这样子
定时的结束了。最难的要属数据迁移了备份。具体的业务就是从另一个库 把有效的数据抽出来插入另外一张表