国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Spring boot實現數據庫讀寫分離的方法

2019-11-26 13:13:23
字體:
來源:轉載
供稿:網友

背景

數據庫配置主從之后,如何在代碼層面實現讀寫分離?

用戶自定義設置數據庫路由

Spring boot提供了AbstractRoutingDataSource根據用戶定義的規則選擇當前的數據庫,這樣我們可以在執行查詢之前,設置讀取從庫,在執行完成后,恢復到主庫。

實現可動態路由的數據源,在每次數據庫查詢操作前執行

ReadWriteSplitRoutingDataSource.java

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** * @author songrgg * @since 1.0 */public class ReadWriteSplitRoutingDataSource extends AbstractRoutingDataSource {  @Override  protected Object determineCurrentLookupKey() {    return DbContextHolder.getDbType();  }}

線程私有路由配置,用于ReadWriteSplitRoutingDataSource動態讀取配置

DbContextHolder.java

/** * @author songrgg * @since 1.0 */public class DbContextHolder {  public enum DbType {    MASTER,    SLAVE  }  private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<>();  public static void setDbType(DbType dbType) {    if(dbType == null){      throw new NullPointerException();    }    contextHolder.set(dbType);  }  public static DbType getDbType() {    return contextHolder.get() == null ? DbType.MASTER : contextHolder.get();  }  public static void clearDbType() {    contextHolder.remove();  }}

AOP優化代碼

利用AOP將設置數據庫的操作從代碼中抽離,這里的粒度控制在方法級別,所以利用注解的形式標注這個方法涉及的數據庫事務只讀,走從庫。

只讀注解,用于標注方法的數據庫操作只走從庫。

ReadOnlyConnection.java

package com.wallstreetcn.hatano.config;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Indicates the database operations is bound to the slave database. * AOP interceptor will set the database to the slave with this interface. * @author songrgg * @since 1.0 */@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface ReadOnlyConnection {}

ReadOnlyConnectionInterceptor.java

import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.core.Ordered;import org.springframework.stereotype.Component;/** * Intercept the database operations, bind database to read-only database as this annotation * is applied. * @author songrgg * @since 1.0 */@Aspect@Componentpublic class ReadOnlyConnectionInterceptor implements Ordered {  private static final Logger logger = LoggerFactory.getLogger(ReadOnlyConnectionInterceptor.class);  @Around("@annotation(readOnlyConnection)")  public Object proceed(ProceedingJoinPoint proceedingJoinPoint, ReadOnlyConnection readOnlyConnection) throws Throwable {    try {      logger.info("set database connection to read only");      DbContextHolder.setDbType(DbContextHolder.DbType.SLAVE);      Object result = proceedingJoinPoint.proceed();      return result;    } finally {      DbContextHolder.clearDbType();      logger.info("restore database connection");    }  }  @Override  public int getOrder() {    return 0;  }}

UserService.java

@ReadOnlyConnectionpublic List<User> getUsers(Integer page, Integer limit) {  return repository.findAll(new PageRequest(page, limit));}

配置Druid數據庫連接池

build.gradle

compile("com.alibaba:druid:1.0.18")

groovy依賴注入

配置dataSource為可路由數據源

context.groovy

import com.alibaba.druid.pool.DruidDataSourceimport DbContextHolderimport ReadWriteSplitRoutingDataSource** SOME INITIALIZED CODE LOAD PROPERTIES **def dataSourceMaster = new DruidDataSource()dataSourceMaster.url = properties.get('datasource.master.url')println("master set to " + dataSourceMaster.url)dataSourceMaster.username = properties.get('datasource.master.username')dataSourceMaster.password = properties.get('datasource.master.password')def dataSourceSlave = new DruidDataSource()dataSourceSlave.url = properties.get('datasource.slave.url')println("slave set to " + dataSourceSlave.url)dataSourceSlave.username = properties.get('datasource.slave.username')dataSourceSlave.password = properties.get('datasource.slave.password') beans {  dataSource(ReadWriteSplitRoutingDataSource) { bean ->    targetDataSources = [        (DbContextHolder.DbType.MASTER): dataSourceMaster,        (DbContextHolder.DbType.SLAVE): dataSourceSlave    ]  }}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 普格县| 福海县| 萨迦县| 铜陵市| 肥东县| 邹平县| 张家港市| 金昌市| 隆德县| 仁布县| 莱阳市| 新乡市| 从江县| 资溪县| 淳安县| 金昌市| 安西县| 分宜县| 无锡市| 宜城市| 昌邑市| 苍梧县| 田东县| 司法| 崇明县| 东丰县| 莒南县| 平潭县| 通州区| 呼和浩特市| 怀安县| 图们市| 启东市| 台中市| 紫阳县| 大埔县| 涿州市| 利川市| 冷水江市| 白沙| 台中县|