一区二区三区电影_国产伦精品一区二区三区视频免费_亚洲欧美国产精品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在线观看_国产精品一二三四
一区二区三区四区五区精品视频| 亚洲人体大胆视频| 欧美日本高清视频| 欧美日韩免费一区二区三区| 欧美日韩中文字幕日韩欧美| 欧美午夜精品久久久久免费视 | 国产亚洲欧美一区二区| 亚洲风情在线资源站| 亚洲无线一线二线三线区别av| 久久精品夜色噜噜亚洲aⅴ| 欧美高清hd18日本| 国产午夜精品在线观看| 亚洲裸体视频| 久久天堂精品| 国产乱码精品一区二区三区不卡| 亚洲精品国产欧美| 久热re这里精品视频在线6| 国产精品成人久久久久| 亚洲国产美国国产综合一区二区| 亚洲欧美美女| 欧美日韩在线影院| 亚洲激情影院| 蜜臀av一级做a爰片久久| 国产亚洲欧美一区二区三区| 中国av一区| 欧美啪啪一区| 亚洲国产精品成人精品| 亚洲欧美日韩一区在线观看| 欧美日韩视频在线一区二区观看视频 | 国产有码在线一区二区视频| 在线中文字幕不卡| 日韩视频精品在线观看| 久久米奇亚洲| 精品999在线观看| 久久久久国产一区二区| 国产精品―色哟哟| 亚洲一区精品视频| 国产精品久久久久久久久久三级| 在线一区二区三区四区| 欧美先锋影音| 午夜亚洲福利| 在线观看不卡av| 欧美大胆a视频| 99视频一区二区三区| 欧美日韩国产成人在线| 亚洲色图自拍| 国产视频综合在线| 久久精品日产第一区二区三区| 韩国三级电影一区二区| 欧美一区二区三区免费观看视频 | 久久伊伊香蕉| 亚洲第一级黄色片| 欧美国产高清| 宅男噜噜噜66国产日韩在线观看| 国产精品成人一区| 欧美一区二区日韩一区二区| 国产一区二区三区直播精品电影 | 精品动漫3d一区二区三区| 久久人91精品久久久久久不卡| 激情校园亚洲| 欧美日韩1080p| 亚洲欧美日韩中文在线制服| 一区二区三区在线视频观看| 欧美日韩大陆在线| 欧美一级在线视频| 亚洲国产精品视频一区| 国产精品毛片一区二区三区 | 最近看过的日韩成人| 国产精品久久久久国产精品日日 | 中文av字幕一区| 国产午夜精品久久| 欧美福利视频在线观看| 亚洲欧美国产日韩天堂区| 亚洲第一中文字幕| 欧美天堂亚洲电影院在线播放| 久久久人成影片一区二区三区观看 | 久久精品免费观看| 亚洲精品视频在线看| 国产精品女人久久久久久| 久久精品人人做人人爽电影蜜月| 日韩亚洲精品电影| 亚洲大片在线观看| 国产亚洲美州欧州综合国| 欧美人妖在线观看| 久久综合网色—综合色88| 亚洲一区二区三区涩| 亚洲大胆人体视频| 国产综合香蕉五月婷在线| 国产精品盗摄久久久| 男人的天堂亚洲| 欧美在线综合| 亚洲一区二区在线| 最新成人在线| 国产曰批免费观看久久久| 国产精品成人播放| 欧美午夜片在线免费观看| 久久久另类综合| 久久成人在线| 久久久999精品视频| 欧美一区二区三区四区夜夜大片 | 亚洲一区二区三区高清| 亚洲国产精品欧美一二99| 在线不卡中文字幕| 亚洲福利视频专区| 亚洲国产一区在线| 亚洲免费观看视频| 99国产精品久久久久久久久久 | 欧美激情在线播放| 欧美成人伊人久久综合网| 免费久久久一本精品久久区| 美日韩在线观看| 欧美激情精品久久久久久久变态| 欧美日本国产| 欧美视频在线看| 国产精品视频第一区| 国产精品一级| 国产一区二区精品久久| 狠狠88综合久久久久综合网| 国产综合欧美在线看| 在线看日韩欧美| 亚洲精品视频在线看| 亚洲一区二区三区在线视频| 欧美一区二区三区精品| 久久久久青草大香线综合精品| 欧美jizzhd精品欧美喷水 | 夜夜狂射影院欧美极品| 一区二区三区欧美亚洲| 亚洲欧美综合一区| 六月天综合网| 国产精品美女久久福利网站| 国产一区二区三区在线免费观看 | 欧美精品电影在线| 国产精品手机在线| 在线日本成人| 欧美亚洲色图校园春色| 欧美激情第10页| 国产视频一区二区三区在线观看| 激情欧美亚洲| 99国产精品自拍| 久久久精彩视频| 国产精品国产自产拍高清av王其 | 亚洲国产99| 亚洲欧美bt| 欧美大片在线观看一区| 国产九九精品视频| 亚洲日本aⅴ片在线观看香蕉| 亚洲欧美文学| 欧美精品国产精品| 国产亚洲一区二区三区在线观看| 99在线视频精品| 久久精品麻豆| 国产精品视频内| 亚洲理伦电影| 久久综合色影院| 国产精品专区第二| 99国产精品国产精品久久| 老鸭窝毛片一区二区三区| 国产精品日韩欧美大师| 99视频在线精品国自产拍免费观看 | 国产一区二区三区网站| 日韩视频第一页| 免费精品99久久国产综合精品| 国产欧美一区二区精品秋霞影院| 日韩视频精品| 欧美日韩国产不卡在线看| 亚洲第一毛片| 久久精品99无色码中文字幕 | 久久av资源网| 国产精品视频导航| 一区二区三区**美女毛片| 欧美激情二区三区| 亚洲成人在线免费| 免费成人av资源网| 在线高清一区| 欧美高清一区| 亚洲精品免费网站| 欧美精品自拍偷拍动漫精品| 91久久黄色| 欧美日韩成人激情| 在线视频一区观看| 国产精品www994| 亚洲欧美日韩国产一区二区三区| 国产精品美女www爽爽爽| 亚洲视频观看| 国产精品一区二区三区久久久| 亚洲午夜高清视频| 国外成人免费视频| 亚洲欧美日韩国产综合在线| 国产精品丝袜白浆摸在线| 欧美一级二级三级蜜桃| 狠狠色综合网| 欧美r片在线| 9l国产精品久久久久麻豆| 国产精品国产精品国产专区不蜜| 亚洲欧美日韩高清| 加勒比av一区二区| 欧美日韩理论| 久久se精品一区二区| 亚洲国产天堂久久综合| 欧美日韩极品在线观看一区|