一区二区三区电影_国产伦精品一区二区三区视频免费_亚洲欧美国产精品va在线观看_国产精品一二三四

聯系我們 - 廣告服務 - 聯系電話:
您的當前位置: > 關注 > > 正文

全球快消息!自定義注解+AOPP 簡化數據源的切換操作

來源:CSDN 時間:2023-01-12 10:34:48

項目中經常會出現需要同時連接兩個數據源的情況,這里還是演示基于MyBatis來配置兩個數據源,并演示如何切換不同的數據源。


(資料圖片)

網上的一些例子都寫的有點冗余,這里我通過自定義注解+AOP的方式,來簡化這種數據源的切換操作。

maven依賴

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950

UTF-8UTF-81.81.1.28.0.7-dmr2.1.81.0.5org.springframework.bootspring-boot-starter-aopmysqlmysql-connector-java${mysql-connector.version}runtimecom.alibabadruid${druid.version}com.baomidoumybatis-plus${mybatis-plus.version}com.baomidoumybatisplus-spring-boot-starter${mybatisplus-spring-boot-starter.version}org.springframework.bootspring-boot-starter-testtestorg.hamcresthamcrest-all1.3test

初始化數據庫

這里我們需要創建兩個數據庫,初始化腳本如下:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849

# -------------------------------------以下是pos業務庫開始-------------------------------------------CREATE DATABASE IF NOT EXISTS pos default charset utf8 COLLATE utf8_general_ci;SET FOREIGN_KEY_CHECKS=0;USE pos;-- 后臺管理用戶表DROP TABLE IF EXISTS `t_user`;CREATE TABLE `t_user` (  `id`                        INT(11) PRIMARY KEY AUTO_INCREMENT COMMENT "主鍵ID",  `username`                  VARCHAR(32) NOT NULL COMMENT "賬號",  `name`                      VARCHAR(16) DEFAULT "" COMMENT "名字",  `password`                  VARCHAR(128) DEFAULT "" COMMENT "密碼",  `salt`                      VARCHAR(64) DEFAULT "" COMMENT "md5密碼鹽",  `phone`                     VARCHAR(32) DEFAULT "" COMMENT "聯系電話",  `tips`                      VARCHAR(255) COMMENT "備注",  `state`                     TINYINT(1) DEFAULT 1 COMMENT "狀態 1:正常 2:禁用",  `created_time`              DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT "創建時間",  `updated_time`              DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT "更新時間") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT="后臺管理用戶表";# 下面是pos數據庫中的插入數據INSERT INTO `t_user` VALUES (1,"admin","系統管理員","123456","www", "17890908889", "系統管理員", 1, "2017-12-12 09:46:12", "2017-12-12 09:46:12");INSERT INTO `t_user` VALUES (2,"aix","張三","123456","eee", "17859569358", "", 1, "2017-12-12 09:46:12", "2017-12-12 09:46:12");# -------------------------------------以下biz業務庫開始-------------------------------------------CREATE DATABASE IF NOT EXISTS pos default charset utf8 COLLATE utf8_general_ci;SET FOREIGN_KEY_CHECKS=0;USE biz;-- 后臺管理用戶表DROP TABLE IF EXISTS `t_user`;CREATE TABLE `t_user` (  `id`                        INT(11) PRIMARY KEY AUTO_INCREMENT COMMENT "主鍵ID",  `username`                  VARCHAR(32) NOT NULL COMMENT "賬號",  `name`                      VARCHAR(16) DEFAULT "" COMMENT "名字",  `password`                  VARCHAR(128) DEFAULT "" COMMENT "密碼",  `salt`                      VARCHAR(64) DEFAULT "" COMMENT "md5密碼鹽",  `phone`                     VARCHAR(32) DEFAULT "" COMMENT "聯系電話",  `tips`                      VARCHAR(255) COMMENT "備注",  `state`                     TINYINT(1) DEFAULT 1 COMMENT "狀態 1:正常 2:禁用",  `created_time`              DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT "創建時間",  `updated_time`              DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT "更新時間") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT="后臺管理用戶表";# 下面是biz數據庫中的插入數據INSERT INTO `t_user` VALUES (1,"admin1","系統管理員","123456","www", "17890908889", "系統管理員", 1, "2017-12-12 09:46:12", "2017-12-12 09:46:12");INSERT INTO `t_user` VALUES (2,"aix1","張三","123456","eee", "17859569358", "", 1, "2017-12-12 09:46:12", "2017-12-12 09:46:12");

可以看到我創建了兩個數據庫pos和biz,同時還初始化了用戶表,并分別插入兩條初始數據。注意用戶名數據不相同。

配置文件

接下來修改application.yml配置文件,如下:

1234567891011121314151617181920212223242526272829303132

###################  自定義配置  ###################xncoding:  muti-datasource-open: true #是否開啟多數據源(true/false)###################  mybatis-plus配置  ###################mybatis-plus:  mapper-locations: classpath*:com/xncoding/pos/common/dao/repository/mapping/*.xml  typeAliasesPackage: >    com.xncoding.pos.common.dao.entity  global-config:    id-type: 0  # 0:數據庫ID自增   1:用戶輸入id  2:全局唯一id(IdWorker)  3:全局唯一ID(uuid)    db-column-underline: false    refresh-mapper: true  configuration:    map-underscore-to-camel-case: true    cache-enabled: true #配置的緩存的全局開關    lazyLoadingEnabled: true #延時加載的開關    multipleResultSetsEnabled: true #開啟的話,延時加載一個屬性時會加載該對象全部屬性,否則按需加載屬性#默認數據源spring:  datasource:    url: jdbc:mysql://127.0.0.1:3306/pos?useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8    username: root    password: 123456#多數據源biz:  datasource:    url: jdbc:mysql://127.0.0.1:3306/biz?useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8    username: root    password: 123456

解釋一下:

這里我添加了一個自定義配置項muti-datasource-open,用來控制是否開啟多數據源支持。這個配置項后面我會用到。 接下來定義MyBatis的配置,最后定義了兩個MySQL數據庫的連接信息,一個是pos庫,一個是biz庫。

動態切換數據源

這里通過Spring的AOP技術實現數據源的動態切換。

多數據源的常量類:

1234

public interface DSEnum {    String DATA_SOURCE_CORE = "dataSourceCore";         //核心數據源    String DATA_SOURCE_BIZ = "dataSourceBiz";            //其他業務的數據源}

datasource的上下文,用來存儲當前線程的數據源類型:

1234567891011121314151617181920212223242526

public class DataSourceContextHolder {    private static final ThreadLocalcontextHolder = new ThreadLocal();    /**     * @param dataSourceType 數據庫類型     * @Description: 設置數據源類型     */    public static void setDataSourceType(String dataSourceType) {        contextHolder.set(dataSourceType);    }    /**     * @Description: 獲取數據源類型     */    public static String getDataSourceType() {        return contextHolder.get();    }    /**     * @Description: 清除數據源類型     */    public static void clearDataSourceType() {        contextHolder.remove();    }}

定義動態數據源,繼承AbstractRoutingDataSource:

1234567

public class DynamicDataSource extends AbstractRoutingDataSource {    @Override    protected Object determineCurrentLookupKey() {        return DataSourceContextHolder.getDataSourceType();    }}

接下來自定義一個注解,用來在Service方法上面注解使用哪個數據源:

1234567891011

/** * 多數據源標識 * * @author xiongneng */@Inherited@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface DataSource {    String name() default "";}

最后,最核心的AOP類定義:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556

/** * 多數據源切換的aop * * @author xiongneng */@Aspect@Component@ConditionalOnProperty(prefix = "xncoding", name = "muti-datasource-open", havingValue = "true")public class MultiSourceExAop implements Ordered {    private Logger log = Logger.getLogger(this.getClass());    @Pointcut(value = "@annotation(com.xncoding.pos.common.annotion.DataSource)")    private void cut() {    }    @Around("cut()")    public Object around(ProceedingJoinPoint point) throws Throwable {        Signature signature = point.getSignature();        MethodSignature methodSignature = null;        if (!(signature instanceof MethodSignature)) {            throw new IllegalArgumentException("該注解只能用于方法");        }        methodSignature = (MethodSignature) signature;        Object target = point.getTarget();        Method currentMethod = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());        DataSource datasource = currentMethod.getAnnotation(DataSource.class);        if (datasource != null) {            DataSourceContextHolder.setDataSourceType(datasource.name());            log.debug("設置數據源為:" + datasource.name());        } else {            DataSourceContextHolder.setDataSourceType(DSEnum.DATA_SOURCE_CORE);            log.debug("設置數據源為:dataSourceCore");        }        try {            return point.proceed();        } finally {            log.debug("清空數據源信息!");            DataSourceContextHolder.clearDataSourceType();        }    }    /**     * aop的順序要早于spring的事務     */    @Override    public int getOrder() {        return 1;    }}

這里使用到了注解@ConditionalOnProperty,只有當我的配置文件中muti-datasource-open=true的時候注解才會生效。

另外還有一個要注意的地方,就是order,aop的順序一定要早于spring的事務,這里我將它設置成1,后面你會看到我將spring事務順序設置成2。

配置類

首先有兩個屬性類:

DruidProperties連接池的屬性類MutiDataSourcePropertiesbiz數據源的屬性類

然后定義配置類:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465

@Configuration@EnableTransactionManagement(order = 2)@MapperScan(basePackages = {"com.xncoding.pos.common.dao.repository"})public class MybatisPlusConfig {    @Autowired    DruidProperties druidProperties;    @Autowired    MutiDataSourceProperties mutiDataSourceProperties;    /**     * 核心數據源     */    private DruidDataSource coreDataSource() {        DruidDataSource dataSource = new DruidDataSource();        druidProperties.config(dataSource);        return dataSource;    }    /**     * 另一個數據源     */    private DruidDataSource bizDataSource() {        DruidDataSource dataSource = new DruidDataSource();        druidProperties.config(dataSource);        mutiDataSourceProperties.config(dataSource);        return dataSource;    }    /**     * 單數據源連接池配置     */    @Bean    @ConditionalOnProperty(prefix = "xncoding", name = "muti-datasource-open", havingValue = "false")    public DruidDataSource singleDatasource() {        return coreDataSource();    }    /**     * 多數據源連接池配置     */    @Bean    @ConditionalOnProperty(prefix = "xncoding", name = "muti-datasource-open", havingValue = "true")    public DynamicDataSource mutiDataSource() {        DruidDataSource coreDataSource = coreDataSource();        DruidDataSource bizDataSource = bizDataSource();        try {            coreDataSource.init();            bizDataSource.init();        } catch (SQLException sql) {            sql.printStackTrace();        }        DynamicDataSource dynamicDataSource = new DynamicDataSource();        HashMaphashMap = new HashMap<>();        hashMap.put(DSEnum.DATA_SOURCE_CORE, coreDataSource);        hashMap.put(DSEnum.DATA_SOURCE_BIZ, bizDataSource);        dynamicDataSource.setTargetDataSources(hashMap);        dynamicDataSource.setDefaultTargetDataSource(coreDataSource);        return dynamicDataSource;    }}

代碼其實很好理解,我就不再多做解釋了。

然后步驟跟普通的集成MyBatis是一樣的,我簡單的過一遍。

實體類

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748

@TableName(value = "t_user")public class User extends Model{private static final long serialVersionUID = 1L;    /**     * 主鍵ID     */    @TableId(value="id", type= IdType.AUTO)    private Integer id;    /**     * 賬號     */    private String username;    /**     * 名字     */    private String name;    /**     * 密碼     */    private String password;    /**     * md5密碼鹽     */    private String salt;    /**     * 聯系電話     */    private String phone;    /**     * 備注     */    private String tips;    /**     * 狀態 1:正常 2:禁用     */    private Integer state;    /**     * 創建時間     */    private Date createdTime;    /**     * 更新時間     */    private Date updatedTime;    // 省略getter/setter方法}

定義DAO

123

public interface UserMapper extends BaseMapper{}

定義Service

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950

@Servicepublic class UserService {    @Resource    private UserMapper userMapper;    /**     * 通過ID查找用戶     * @param id     * @return     */    public User findById(Integer id) {        return userMapper.selectById(id);    }    /**     * 通過ID查找用戶     * @param id     * @return     */    @DataSource(name = DSEnum.DATA_SOURCE_BIZ)    public User findById1(Integer id) {        return userMapper.selectById(id);    }    /**     * 新增用戶     * @param user     */    public void insertUser(User user) {        userMapper.insert(user);    }    /**     * 修改用戶     * @param user     */    public void updateUser(User user) {        userMapper.updateById(user);    }    /**     * 刪除用戶     * @param id     */    public void deleteUser(Integer id) {        userMapper.deleteById(id);    }}

這里唯一要說明的就是我在方法findById1()上面增加了注解@DataSource(name = DSEnum.DATA_SOURCE_BIZ),這樣這個方法就會訪問biz數據庫。

注意,不加注解就會訪問默認數據庫pos。

測試

最后編寫一個簡單的測試,我只測試findById()方法和findById1()方法,看它們是否訪問的是不同的數據源。

12345678910111213141516171819202122

@RunWith(SpringRunner.class)@SpringBootTestpublic class ApplicationTests {    private static final Logger log = LoggerFactory.getLogger(ApplicationTests.class);    @Resource    private UserService userService;    /**     * 測試增刪改查     */    @Test    public void test() {        // 核心數據庫中的用戶id=1        User user = userService.findById(1);        assertThat(user.getUsername(), is("admin"));        // biz數據庫中的用戶id=1        User user1 = userService.findById1(1);        assertThat(user1.getUsername(), is("admin1"));    }}

運行測試,結果顯示為green bar,成功!

責任編輯:

標簽:

相關推薦:

精彩放送:

新聞聚焦
Top 一区二区三区电影_国产伦精品一区二区三区视频免费_亚洲欧美国产精品va在线观看_国产精品一二三四
欧美乱大交xxxxx| 香蕉乱码成人久久天堂爱免费 | 国产精品女人网站| 国产嫩草影院久久久久| 激情婷婷欧美| 亚洲欧美日韩久久精品| 欧美国内亚洲| 国产亚洲激情在线| 亚洲一区二区三区四区视频 | 99re在线精品| 久久久久www| 国产精品视频自拍| 亚洲精品视频啊美女在线直播| 新狼窝色av性久久久久久| 老司机一区二区| 国产区精品在线观看| 亚洲视频狠狠| 欧美日韩精品一区二区| 亚洲激情自拍| 麻豆精品一区二区综合av| 国产日本精品| 欧美一区二区三区免费视频| 国产精品爱啪在线线免费观看| 亚洲黄色天堂| 免费高清在线一区| 激情五月***国产精品| 欧美亚洲综合久久| 国产精品美女久久久久久久| 中国成人黄色视屏| 欧美天堂亚洲电影院在线播放| 最近看过的日韩成人| 欧美va天堂在线| 亚洲黄色视屏| 欧美大片在线看免费观看| 狠狠色综合网站久久久久久久| 欧美亚洲一区三区| 国产亚洲免费的视频看| 久久www成人_看片免费不卡| 国产日韩欧美91| 久久久亚洲高清| 亚洲国产一区视频| 欧美精品自拍| 亚洲永久精品大片| 国产日韩精品电影| 玖玖精品视频| 亚洲免费成人av| 国产精品久久久久久户外露出| 亚洲永久视频| 国产一区二区三区在线观看视频 | 欧美一区二区视频网站| 国产日韩精品在线| 久久综合亚州| 一片黄亚洲嫩模| 国产精品一区久久久久| 久久精品91久久香蕉加勒比| 国产欧美精品一区二区三区介绍 | 91久久久久久国产精品| 欧美精品福利视频| 亚洲午夜免费视频| 激情久久久久久久| 欧美日韩免费高清| 久久爱www.| 亚洲黄一区二区| 国产伦精品一区二区三区免费| 久久久久久穴| 最近中文字幕日韩精品| 国产精品久久久久久久久久久久久 | 国产午夜精品一区理论片飘花| 久久性天堂网| 亚洲日韩欧美视频一区| 国产精品成人免费视频| 欧美一区观看| 亚洲国产成人tv| 国产亚洲欧美aaaa| 欧美日韩不卡| 久久久精品2019中文字幕神马| 一本到12不卡视频在线dvd| 国产午夜精品麻豆| 欧美成人性网| 亚洲欧美伊人| 99re8这里有精品热视频免费| 国模精品一区二区三区色天香| 欧美午夜女人视频在线| 久久久久久久一区二区| 亚洲综合国产| 一本久道久久综合狠狠爱| 在线日韩一区二区| 国产真实乱子伦精品视频| 国产精品日本一区二区 | 欧美日韩国产一区精品一区| 99视频一区二区| 激情成人综合| 国产精品视频男人的天堂| 另类专区欧美制服同性| 午夜精品亚洲| 亚洲视频自拍偷拍| 亚洲精品网址在线观看| 在线日韩视频| 136国产福利精品导航网址| 国产欧美大片| 国产农村妇女毛片精品久久莱园子| 欧美日韩中文在线观看| 欧美激情第1页| 欧美不卡激情三级在线观看| 另类激情亚洲| 欧美ab在线视频| 欧美成人嫩草网站| 欧美成人午夜视频| 欧美国产日韩二区| 欧美人与性禽动交情品 | 91久久在线播放| 国产精品s色| 久久久www免费人成黑人精品 | 在线成人国产| 好看的av在线不卡观看| 国模精品一区二区三区| 精品动漫3d一区二区三区免费| 国产综合久久久久久鬼色| 韩国三级电影一区二区| 在线观看视频日韩| 亚洲欧洲日本专区| 一本色道久久综合亚洲精品按摩| 亚洲精品综合| 亚洲一区日韩| 国产精品久久久久免费a∨大胸| 欧美视频在线一区二区三区| 国产精品成人一区二区网站软件| 国产精品免费区二区三区观看| 国产一区二区三区网站| 亚洲第一毛片| 亚洲大片在线| 免费久久99精品国产| 亚洲午夜激情| 国产三级欧美三级日产三级99| 欧美一区二区在线观看| 国产精品视频久久久| 欧美午夜片在线观看| 亚洲一区二区三区四区在线观看 | 欧美激情国产精品| 影音先锋亚洲一区| 国产精品一区二区在线观看不卡 | 亚洲丝袜av一区| 在线一区二区三区四区| 欧美在线视屏 | 亚洲精品自在在线观看| 午夜精品一区二区三区四区| 久久一区亚洲| 国产精品大片wwwwww| 亚洲缚视频在线观看| 亚洲午夜一区二区| 欧美成人免费网| 国产在线乱码一区二区三区| a91a精品视频在线观看| 久久久久久久激情视频| 国产精品成人国产乱一区| 在线观看精品视频| 欧美专区日韩视频| 国产精品高清在线| 日韩视频免费看| 久久一区二区三区四区五区| 国产农村妇女毛片精品久久莱园子| 亚洲日韩欧美视频一区| 欧美在线观看日本一区| 欧美午夜精品久久久久久人妖| 亚洲第一在线综合在线| 午夜精品一区二区在线观看| 欧美性开放视频| 亚洲精品四区| 欧美国产日韩在线观看| 在线国产精品一区| 久久精品国内一区二区三区| 国产精品久久久免费| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 国产三级欧美三级| 中文精品视频| 欧美精品一区二区三区在线播放| 国产亚洲激情在线| 亚洲欧美自拍偷拍| 国产精品一二三四| 亚洲男人av电影| 国产精品久久精品日日| 一区二区欧美精品| 欧美日韩国语| 亚洲一区二区三区久久| 国产精品一区二区黑丝| 亚洲三级视频| 欧美成人精品影院| 日韩一级精品视频在线观看| 欧美精品久久99| 一区二区三区欧美亚洲| 欧美日韩一区二区三区免费看 | 欧美视频在线观看 亚洲欧| 亚洲日本aⅴ片在线观看香蕉| 欧美国产激情二区三区| 9色国产精品| 国产精品日韩欧美一区二区三区| 午夜精品久久| 国产一区三区三区| 男人插女人欧美| 欧美区日韩区|