91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot中怎么利用mybatis實現數據庫的讀寫分離

發布時間:2021-08-10 17:07:43 來源:億速云 閱讀:153 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關springboot中怎么利用mybatis實現數據庫的讀寫分離,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

首先,我們需要兩個數據庫實例,一為master,一為slave。

所有的寫操作,我們在master節點上操作

所有的讀操作,我們在slave節點上操作

需要注意的是:對于一次有讀有寫的事務,事務內的讀操作也不應該在slave節點上,所有操作都應該在master節點上先跑起來兩個pg的實例,其中15432端口對應的master節點,15433端口對應的slave節點:

docker run \ --name pg-master \ -p 15432:5432 \ --env 'PG_PASSWORD=postgres' \ --env 'REPLICATION_MODE=master' \ --env 'REPLICATION_USER=repluser' \  --env 'REPLICATION_PASS=repluserpass' \ -d sameersbn/postgresql:10-2docker run \ --name pg-slave \ -p 15433:5432 \ --link pg-master:master \ --env 'PG_PASSWORD=postgres' \ --env 'REPLICATION_MODE=slave' \ --env 'REPLICATION_SSLMODE=prefer' \ --env 'REPLICATION_HOST=master' \ --env 'REPLICATION_PORT=5432' \ --env 'REPLICATION_USER=repluser' \  --env 'REPLICATION_PASS=repluserpass' \ -d sameersbn/postgresql:10-2

實現

整個實現主要有3個部分:

配置兩個數據源  實現AbstractRoutingDataSource來動態的使用數據源  實現mybatis plugin來動態的選擇數據源

配置數據源

將數據庫連接信息配置到application.yml文件中

spring: mvc:  servlet:   path: /apidatasource: write:  driver-class-name: org.postgresql.Driver  url: "${DB_URL_WRITE:jdbc:postgresql://localhost:15432/postgres}"  username: "${DB_USERNAME_WRITE:postgres}"  password: "${DB_PASSWORD_WRITE:postgres}" read:  driver-class-name: org.postgresql.Driver  url: "${DB_URL_READ:jdbc:postgresql://localhost:15433/postgres}"  username: "${DB_USERNAME_READ:postgres}"  password: "${DB_PASSWORD_READ:postgres}"mybatis-plus: configuration:  map-underscore-to-camel-case: true

write寫數據源,對應到master節點的15432端口

read讀數據源,對應到slave節點的15433端口

將兩個數據源信息注入為DataSourceProperties:

@Configurationpublic class DataSourcePropertiesConfig {  @Primary  @Bean("writeDataSourceProperties")  @ConfigurationProperties("datasource.write")  public DataSourceProperties writeDataSourceProperties() {    return new DataSourceProperties();  }  @Bean("readDataSourceProperties")  @ConfigurationProperties("datasource.read")  public DataSourceProperties readDataSourceProperties() {    return new DataSourceProperties();  }}

實現AbstractRoutingDataSource

spring提供了AbstractRoutingDataSource,提供了動態選擇數據源的功能,替換原有的單一數據源后,即可實現讀寫分離:

@Componentpublic class CustomRoutingDataSource extends AbstractRoutingDataSource {  @Resource(name = "writeDataSourceProperties")  private DataSourceProperties writeProperties;  @Resource(name = "readDataSourceProperties")  private DataSourceProperties readProperties;  @Override  public void afterPropertiesSet() {    DataSource writeDataSource =       writeProperties.initializeDataSourceBuilder().type(DruidDataSource.class).build();    DataSource readDataSource =       readProperties.initializeDataSourceBuilder().type(DruidDataSource.class).build();        setDefaultTargetDataSource(writeDataSource);    Map<Object, Object> dataSourceMap = new HashMap<>();    dataSourceMap.put(WRITE_DATASOURCE, writeDataSource);    dataSourceMap.put(READ_DATASOURCE, readDataSource);    setTargetDataSources(dataSourceMap);    super.afterPropertiesSet();  }  @Override  protected Object determineCurrentLookupKey() {    String key = DataSourceHolder.getDataSource();    if (key == null) {       // default datasource      return WRITE_DATASOURCE;    }    return key;  }}

AbstractRoutingDataSource內部維護了一個Map<Object, Object>的Map

在初始化過程中,我們將write、read兩個數據源加入到這個map

調用數據源時:determineCurrentLookupKey()方法返回了需要使用的數據源對應的key

當前線程需要使用的數據源對應的key,是在DataSourceHolder類中維護的:

public class DataSourceHolder {  public static final String WRITE_DATASOURCE = "write";  public static final String READ_DATASOURCE = "read";  private static final ThreadLocal<String> local = new ThreadLocal<>();  public static void putDataSource(String dataSource) {    local.set(dataSource);  }  public static String getDataSource() {    return local.get();  }  public static void clearDataSource() {    local.remove();  }}

實現mybatis plugin

上面提到了當前線程使用的數據源對應的key,這個key需要在mybatis plugin根據sql類型來確定MybatisDataSourceInterceptor類:

@Component@Intercepts({    @Signature(type = Executor.class, method = "update",        args = {MappedStatement.class, Object.class}),    @Signature(type = Executor.class, method = "query",        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),    @Signature(type = Executor.class, method = "query",        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class,            CacheKey.class, BoundSql.class})})public class MybatisDataSourceInterceptor implements Interceptor {  @Override  public Object intercept(Invocation invocation) throws Throwable {    boolean synchronizationActive = TransactionSynchronizationManager.isSynchronizationActive();    if(!synchronizationActive) {      Object[] objects = invocation.getArgs();      MappedStatement ms = (MappedStatement) objects[0];      if (ms.getSqlCommandType().equals(SqlCommandType.SELECT)) {        DataSourceHolder.putDataSource(DataSourceHolder.READ_DATASOURCE);      }    }    return invocation.proceed();  }  @Override  public Object plugin(Object target) {    return Plugin.wrap(target, this);  }  @Override  public void setProperties(Properties properties) {  }}

僅當未在事務中,并且調用的sql是select類型時,在DataSourceHolder中將數據源設為read

其他情況下,AbstractRoutingDataSource會使用默認的write數據源

至此,項目已經可以自動的在讀、寫數據源間切換,無需修改原有的業務代碼

最后,提供demo使用依賴版本

<parent>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-parent</artifactId>  <version>2.1.7.RELEASE</version>  <relativePath/> <!-- lookup parent from repository --></parent><dependencies>  <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter</artifactId>  </dependency>  <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId>  </dependency>  <dependency>    <groupId>org.postgresql</groupId>    <artifactId>postgresql</artifactId>    <version>42.2.2</version>  </dependency>  <dependency>    <groupId>com.alibaba</groupId>    <artifactId>druid-spring-boot-starter</artifactId>    <version>1.1.9</version>  </dependency>  <dependency>    <groupId>com.baomidou</groupId>    <artifactId>mybatisplus-spring-boot-starter</artifactId>    <version>1.0.5</version>  </dependency>  <dependency>    <groupId>com.baomidou</groupId>    <artifactId>mybatis-plus</artifactId>    <version>2.1.9</version>  </dependency>  <dependency>    <groupId>io.springfox</groupId>    <artifactId>springfox-swagger2</artifactId>    <version>2.8.0</version>  </dependency>  <dependency>    <groupId>io.springfox</groupId>    <artifactId>springfox-swagger-ui</artifactId>    <version>2.8.0</version>  </dependency>  <dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.16.20</version>  </dependency>  <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-test</artifactId>    <scope>test</scope>  </dependency></dependencies>

關于springboot中怎么利用mybatis實現數據庫的讀寫分離就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

富裕县| 安多县| 噶尔县| 沁源县| 南皮县| 凤山县| 团风县| 侯马市| 朝阳市| 华坪县| 龙海市| 合江县| 太仓市| 菏泽市| 平山县| 大田县| 建水县| 武威市| 忻州市| 赤峰市| 鸡西市| 保德县| 乌拉特前旗| 茌平县| 和龙市| 太白县| 南岸区| 丰顺县| 福安市| 玉田县| 阿克苏市| 元氏县| 富平县| 黄梅县| 无为县| 邹平县| 孟村| 修武县| 南皮县| 荆州市| 玉树县|