日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【springboot整合多数据源】

發布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【springboot整合多数据源】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

springboot整合多數據源

  • 配置多數據
    • application.yaml
    • 動態路由數據源
    • 數據源上下文管理
    • 數據源切面
    • MybatisPlusConfig配置
    • 自定義方法注入器
  • 擴展配置,幫助我們批量更新、新增等操作
    • RootMapper
    • InsertBatchMethod
    • UpdateBatchMethod

配置多數據

application.yaml

spring:application:name: erp9-synaop:proxy-target-class: trueauto: truemain:allow-bean-definition-overriding: truedatasource:erp9:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.80.211:3306/1231?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8&allowPublicKeyRetrieval=trueusername: b1b_goodspassword: asdadinitialSize: 10minIdle: 10maxActive: 80type: com.alibaba.druid.pool.DruidDataSourcerate:driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriverurl: jdbc:sqlserver://101.200.55.149:6522;Databasename=sacsacusername: ascacpassword: 121sadsinitialSize: 5minIdle: 5maxActive: 40type: com.alibaba.druid.pool.DruidDataSource # 日志配置 mybatis-plus:mapper-locations: classpath:xml/**/*Mapper.xmltypeAliasesPackage: com.yuanda.erp9.syn.entityconfiguration:map-underscore-to-camel-case: true# console輸出日志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

動態路由數據源

package com.yuanda.erp9.syn.config;import lombok.extern.slf4j.Slf4j; import org.springframework.core.annotation.Order; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/*** 動態路由數據源*/ @Order(1) @Slf4j public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {String datasource = DynamicDataSourceContextHolder.getDataSourceKey();super.setDefaultTargetDataSource(datasource);log.debug("使用數據源 {}", datasource);return datasource;} }

數據源上下文管理

package com.yuanda.erp9.syn.config;import com.yuanda.erp9.syn.contant.DatabaseGlobal; import java.util.ArrayList; import java.util.Collection; import java.util.List;/*** @ClassName DynamicDataSourceContextHolder* @Description 數據上下文管理* @Date 2022/12/15* @Author myq*/ public class DynamicDataSourceContextHolder {/*** 實際上就是開啟多個線程,每個線程進行初始化一個數據源*/private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<String>() {/*** 將 master 數據源的 key作為默認數據源的 key*/@Overrideprotected String initialValue() {return DatabaseGlobal.erp9;}};/*** 數據源的 key集合,用于切換時判斷數據源是否存在*/public static List<Object> dataSourceKeys = new ArrayList<Object>();/*** 切換數據源** @param key*/public static void setDataSourceKey(String key) {CONTEXT_HOLDER.set(key);}/*** 獲取數據源** @return*/public static String getDataSourceKey() {return CONTEXT_HOLDER.get();}/*** 重置數據源*/public static void clearDataSourceKey() {CONTEXT_HOLDER.remove();}/*** 判斷是否包含數據源** @param key 數據源key* @return*/public static boolean containDataSourceKey(String key) {return dataSourceKeys.contains(key);}/*** 添加數據源keys** @param keys* @return*/public static boolean addDataSourceKeys(Collection<? extends Object> keys) {return dataSourceKeys.addAll(keys);} }

數據源切面

package com.yuanda.erp9.syn.config;import com.yuanda.erp9.syn.contant.DatabaseGlobal; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component;@Component @Order(value = -100) @Aspect @Slf4j public class DataSourceAspect {@Pointcut("execution( * com.yuanda.erp9.syn.service.erp9.impl..*.*(..))")private void erp9Aspect() {}@Pointcut("execution(* com.yuanda.erp9.syn.service.rate.impl..*.*(..))")private void rateAspect() {}@Before("erp9Aspect()")public void cyz() {log.debug("切換到{} 數據源...", DatabaseGlobal.erp9);DynamicDataSourceContextHolder.setDataSourceKey(DatabaseGlobal.erp9);}@Before("rateAspect()")public void pveStandard() {log.debug("切換到{} 數據源...", DatabaseGlobal.rate);DynamicDataSourceContextHolder.setDataSourceKey(DatabaseGlobal.rate);} }

MybatisPlusConfig配置

package com.yuanda.erp9.syn.config;import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; import com.alibaba.druid.wall.WallConfig; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.config.GlobalConfig; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import com.yuanda.erp9.syn.contant.DatabaseGlobal; import com.yuanda.erp9.syn.core.CustomizedSqlInjector; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.type.JdbcType; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; 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.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map;/*** @ClassName MybatisPlusConfig* @Description 配置文件-自定義sql注入器* @Date 2022/11/16* @Author myq*/ @MapperScan({"com.yuanda.erp9.syn.mapper.erp9", "com.yuanda.erp9.syn.mapper.rate"}) @Configuration @EnableTransactionManagement @ConfigurationProperties(prefix = "mybatis-plus") public class MybatisPlusConfig {/*** 可以寫死 可以沖配置文件中讀取*/private Class logImpl;static {System.setProperty("druid.mysql.usePingMethod","false");}@Beanpublic CustomizedSqlInjector customizedSqlInjector() {return new CustomizedSqlInjector();}/*** 這個bean可以幫助我們一次執行多條dml語句,沒有哦這個配置會出現執行多次sql會出現報錯。*/@Beanpublic WallConfig wallConfig() {WallConfig config = new WallConfig();config.setMultiStatementAllow(true);//允許一次執行多條語句config.setNoneBaseStatementAllow(true);//允許非基本語句的其他語句return config;}@Bean(name = DatabaseGlobal.erp9)@ConfigurationProperties(prefix = "spring.datasource.erp9")public DataSource erp9() {return DruidDataSourceBuilder.create().build();}@Bean(name = DatabaseGlobal.rate)@ConfigurationProperties(prefix = "spring.datasource.rate")public DataSource rate() {return DruidDataSourceBuilder.create().build();}/*** 動態數據源配置** @return*/@Bean@Primarypublic DataSource multipleDataSource(@Qualifier(DatabaseGlobal.erp9) DataSource erp9DataSource,@Qualifier(DatabaseGlobal.rate) DataSource rateDataSource) {DynamicDataSource dynamicDataSource = new DynamicDataSource();Map<Object, Object> targetDataSources = new HashMap<Object, Object>();targetDataSources.put(DatabaseGlobal.erp9, erp9DataSource);targetDataSources.put(DatabaseGlobal.rate, rateDataSource);dynamicDataSource.setTargetDataSources(targetDataSources);// 程序默認數據源,這個要根據程序調用數據源頻次,經常把常調用的數據源作為默認dynamicDataSource.setDefaultTargetDataSource(erp9DataSource);return dynamicDataSource;}@Bean("sqlSessionFactory")public SqlSessionFactory sqlSessionFactory(@Qualifier(DatabaseGlobal.erp9) DataSource erp9DataSource,@Qualifier(DatabaseGlobal.rate) DataSource rateDataSource) throws Exception {MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();// 多數據源必須設置sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:xml/**/*Mapper.xml"));sqlSessionFactory.setDataSource(multipleDataSource(erp9DataSource, rateDataSource));MybatisConfiguration configuration = new MybatisConfiguration();configuration.setJdbcTypeForNull(JdbcType.NULL);configuration.setMapUnderscoreToCamelCase(true);configuration.setCacheEnabled(false);configuration.setLogImpl(logImpl);sqlSessionFactory.setGlobalConfig(globalConfiguration());sqlSessionFactory.setConfiguration(configuration);return sqlSessionFactory.getObject();}@Beanpublic GlobalConfig globalConfiguration() {GlobalConfig conf = new GlobalConfig();// 自定義的注入需要在這里進行配置conf.setSqlInjector(customizedSqlInjector());return conf;}}

自定義方法注入器

package com.yuanda.erp9.syn.core;import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; import org.springframework.stereotype.Component;import java.util.List;/*** 自定義方法SQL注入器*/ @Component public class CustomizedSqlInjector extends DefaultSqlInjector {/*** 如果只需增加方法,保留mybatis plus自帶方法,* 可以先獲取super.getMethodList(),再添加add*/@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);## 這倆是mybatisPlus實現的批量更新操作 也可以注釋掉methodList.add(new InsertBatchMethod());methodList.add(new UpdateBatchMethod());return methodList;} }

擴展配置,幫助我們批量更新、新增等操作

RootMapper

package com.yuanda.erp9.syn.core;import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.toolkit.Constants; import org.apache.ibatis.annotations.Param;import java.util.List;/*** 根Mapper,給表Mapper繼承用的,可以自定義通用方法* {@link com.baomidou.mybatisplus.core.mapper.BaseMapper}* {@link com.baomidou.mybatisplus.extension.service.IService}* {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl}*/ public interface RootMapper<T> extends BaseMapper<T> {/*** 自定義批量插入* 如果要自動填充,@Param(xx) xx參數名必須是 list/collection/array 3個的其中之一*/int insertBatch(@Param("list") List<T> list);/*** 自定義批量更新,條件為主鍵* 如果要自動填充,@Param(xx) xx參數名必須是 list/collection/array 3個的其中之一*/int updateBatch(@Param("list") List<T> list);}

InsertBatchMethod

package com.yuanda.erp9.syn.core;import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.metadata.TableInfo; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.keygen.NoKeyGenerator; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource;/*** 批量插入方法實現*/ @Slf4j public class InsertBatchMethod extends AbstractMethod {/*** insertBatch into user(id, name, age) values (1, "a", 17), (2, "b", 18);<script>insertBatch into user(id, name, age) values<foreach collection="list" item="item" index="index" open="(" separator="),(" close=")">#{item.id}, #{item.name}, #{item.age}</foreach></script>*/@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {final String sql = "<script>insert into %s %s values %s</script>";final String fieldSql = prepareFieldSql(tableInfo);final String valueSql = prepareValuesSql(tableInfo);final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);log.debug("sqlResult----->{}", sqlResult);SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);// 第三個參數必須和RootMapper的自定義方法名一致return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, new NoKeyGenerator(), null, null);}private String prepareFieldSql(TableInfo tableInfo) {StringBuilder fieldSql = new StringBuilder();fieldSql.append(tableInfo.getKeyColumn()).append(",");tableInfo.getFieldList().forEach(x -> {fieldSql.append(x.getColumn()).append(",");});fieldSql.delete(fieldSql.length() - 1, fieldSql.length());fieldSql.insert(0, "(");fieldSql.append(")");return fieldSql.toString();}private String prepareValuesSql(TableInfo tableInfo) {final StringBuilder valueSql = new StringBuilder();valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));valueSql.delete(valueSql.length() - 1, valueSql.length());valueSql.append("</foreach>");return valueSql.toString();} }

UpdateBatchMethod

package com.yuanda.erp9.syn.core;import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.metadata.TableInfo; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource;/*** 批量更新方法實現,條件為主鍵,選擇性更新*/ @Slf4j public class UpdateBatchMethod extends AbstractMethod {/*** update user set name = "a", age = 17 where id = 1;* update user set name = "b", age = 18 where id = 2;<script><foreach collection="list" item="item" separator=";">update user<set><if test="item.name != null and item.name != ''">name = #{item.name,jdbcType=VARCHAR},</if><if test="item.age != null">age = #{item.age,jdbcType=INTEGER},</if></set>where id = #{item.id,jdbcType=INTEGER}</foreach></script>*/@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {String sql = "<script>\n<foreach collection=\"list\" item=\"item\" separator=\";\">\nupdate %s %s where %s=#{%s} %s\n</foreach>\n</script>";String additional = tableInfo.isWithVersion() ? tableInfo.getVersionFieldInfo().getVersionOli("item", "item.") : "" + tableInfo.getLogicDeleteSql(true, true);String setSql = sqlSet(tableInfo.isWithLogicDelete(), false, tableInfo, false, "item", "item.");String sqlResult = String.format(sql, tableInfo.getTableName(), setSql, tableInfo.getKeyColumn(), "item." + tableInfo.getKeyProperty(), additional);log.debug("sqlResult----->{}", sqlResult);SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);// 第三個參數必須和RootMapper的自定義方法名一致return this.addUpdateMappedStatement(mapperClass, modelClass, "updateBatch", sqlSource);}}

總結

以上是生活随笔為你收集整理的【springboot整合多数据源】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲精品你懂的 | 91精品啪在线观看国产线免费 | 国产女女 | 电影桑叶2在线播放完整版 222aaa | 人妻换人妻仑乱 | 九色视频丨porny丨丝袜 | 国产喷白浆一区二区三区 | 免费污视频在线观看 | 狠狠人妻久久久久久综合麻豆 | 日剧网| 亚洲欧洲一区二区在线观看 | 日韩骚片| 日韩亚州 | 毛片免费播放 | 福利色导航 | 国产精品12页| 天天干天天操天天玩 | 吻胸摸激情床激烈视频大胸 | 中文字幕+乱码+中文字幕一区 | av狠狠| 色www亚洲国产张柏芝 | 毛片精品 | 黄页在线播放 | 大桥未久中文字幕 | 亚洲www视频 | 干极品美女 | 美女久久久久久久 | 欧美人与按摩师xxxx | 无人在线观看高清视频 单曲 | 一个色综合久久 | www.日韩在线观看 | 最新色站| 性高跟鞋xxxxhd人妖 | 亚洲福利av | 美国性生活大片 | 国产精品日日夜夜 | 伊人中文字幕在线观看 | 综合久久久久综合 | 三级精品在线 | 一亲二脱三插 | 国产精品女教师 | 国产原创视频在线 | 午夜有码 | 欧美熟妇精品久久久久久 | 男人天堂导航 | 日韩精品www| 内谢少妇xxxxx8老少交视频 | 九九热视频在线播放 | 嫩草视频免费观看 | 国产欧美精品一区二区三区app | 在线欧美亚洲 | 999久久| 欧美三级午夜理伦三级小说 | 亚洲一区二区三 | youjizz中国少妇 | 国产一级淫片a视频免费观看 | 日本成人在线看 | 欧美成人福利视频 | 在线视频日韩欧美 | 爆操网站 | www男人的天堂 | 精精国产xxxx视频在线播放 | 久久99免费视频 | 手机看片福利久久 | 黄页视频在线免费观看 | 久久久精品影院 | 少妇太爽了太深了太硬了 | 欧美 亚洲 另类 偷偷 自拍 | 最近2018年手机中文字幕版 | 午夜宅男在线 | 亚洲美女视频在线 | 热久久久久久久 | 国产素人在线观看 | 国产伦精品一区二区三区照片91 | julia一区二区中文久久97 | 91精品美女 | 啪啪福利 | 色婷婷在线视频 | 国产三级久久久久 | 国产性猛交xxxx免费看久久 | 国产精品一区二区自拍 | 亚洲日本在线观看视频 | 色图综合网 | www.在线观看麻豆 | 先锋影音久久 | 国产日韩成人内射视频 | 超碰在线观看免费版 | 无码国产伦一区二区三区视频 | 欧美精品久久96人妻无码 | 久草热视频| 性歌舞团一区二区三区视频 | 九一国产在线 | 免费在线看黄的网站 | 韩国伦理在线看 | 国产欧美一区二区三区四区 | 国产东北真实交换多p免视频 | 亚洲一区二区三区电影 | 激情网av| 亚洲一区网站 |