mysql+spring+mybatisデータベース読み書き分離を実現するコード配置


シーン:データソースを読み、データソースを書きます。
原理:springの「org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource」という抽象類によって実現され、名前を見るとルートデータソースのものであることが分かります。この種類には一つの方法があります。

/** 
 * Determine the current lookup key. This will typically be 
 * implemented to check a thread-bound transaction context. 
 * <p>Allows for arbitrary keys. The returned key needs 
 * to match the stored lookup key type, as resolved by the 
 * {@link #resolveSpecifiedLookupKey} method. 
 */ 
protected abstract Object determineCurrentLookupKey(); 
データベースに行くたびに、この方法を呼び出して対応するデータソースを探します。戻り値とは、対応するデータソースのLookUpKeyです。このLookUpKeyはどこで定義されていますか?下のdataBase.xmlの構成を見てください。

<!--       --> 
<bean id="dataSourceRW" class="org.logicalcobwebs.proxool.ProxoolDataSource"> 
  <property name="alias" value="ihotelRW"></property> 
  <property name="delegateProperties"> 
    <value>user=${jdbc.username},password=${jdbc.password} 
    </value> 
  </property> 
  <property name="user" value="${jdbc.username}" /> 
  <property name="password" value="${jdbc.password}" /> 
  <property name="driver" value="${jdbc.driverClassName}" /> 
  <property name="driverUrl" value="${jdbc.url}" /> 
  <property name="maximumConnectionCount" value="${jdbc.maximumConnectionCount}"></property> 
  <property name="maximumActiveTime" value="${jdbc.maximumActiveTime}"></property> 
  <property name="maximumConnectionLifetime" value="${jdbc.maximumConnectionLifetime}"></property> 
  <property name="prototypeCount" value="${jdbc.prototypeCount}"></property> 
  <property name="houseKeepingSleepTime" value="${jdbc.houseKeepingSleepTime}"></property> 
  <property name="simultaneousBuildThrottle" value="${jdbc.simultaneousBuildThrottle}"></property> 
  <property name="houseKeepingTestSql" value="${jdbc.houseKeepingTestSql}"></property> 
  <property name="verbose" value="${jdbc.verbose}"></property> 
  <property name="statistics" value="${jdbc.statistics}"></property> 
  <property name="statisticsLogLevel" value="${jdbc.statisticsLogLevel}"></property> 
</bean> 
  <!--     --> 
  <bean id="dataSourceR" class="org.logicalcobwebs.proxool.ProxoolDataSource"> 
    <property name="alias" value="ihotelR"></property> 
    <property name="delegateProperties"> 
      <value>user=${jdbc.r.username},password=${jdbc.r.password} 
      </value> 
    </property> 
    <property name="user" value="${jdbc.r.username}" /> 
    <property name="password" value="${jdbc.r.password}" /> 
    <property name="driver" value="${jdbc.r.driverClassName}" /> 
    <property name="driverUrl" value="${jdbc.r.url}" /> 
    <property name="maximumConnectionCount" value="${jdbc.maximumConnectionCount}"></property> 
    <property name="maximumActiveTime" value="${jdbc.maximumActiveTime}"></property> 
    <property name="maximumConnectionLifetime" value="${jdbc.maximumConnectionLifetime}"></property> 
    <property name="prototypeCount" value="${jdbc.prototypeCount}"></property> 
    <property name="houseKeepingSleepTime" value="${jdbc.houseKeepingSleepTime}"></property> 
    <property name="simultaneousBuildThrottle" value="${jdbc.simultaneousBuildThrottle}"></property> 
    <property name="houseKeepingTestSql" value="${jdbc.houseKeepingTestSql}"></property> 
    <property name="verbose" value="${jdbc.verbose}"></property> 
    <property name="statistics" value="${jdbc.statistics}"></property> 
    <property name="statisticsLogLevel" value="${jdbc.statisticsLogLevel}"></property> 
  </bean> 
  <!--       --> 
  <bean id="dynamicDataSource" class="com.dao.datasource.DynamicDataSource"> 
    <!--   key-value      --> 
    <property name="targetDataSources"> 
      <map> 
        <entry value-ref="dataSourceRW" key="dataSourceKeyRW"></entry> 
        <entry value-ref="dataSourceR" key="dataSourceKeyR"></entry> 
      </map> 
    </property> 
    <property name="defaultTargetDataSource" ref="dataSourceRW" />   
  </bean> 
<!--mybatis Spring      --> 
<bean id="sqlSessionFactory" name="sqlSessionFactory" 
  class="org.mybatis.spring.SqlSessionFactoryBean"> 
  <property name="configLocation" value="classpath:conf/core/sqlMapConfig.xml" /> 
  <property name="dataSource" ref="dynamicDataSource" /> 
</bean> 
ダイナミックデータソースdynamicDatasourceのdata SourceKeyRW、data SourceKeyRは

protected abstract Object determineCurrentLookupKey(); 
この方法は戻り値です。この方法の戻り値はどのように設定しますか?必要に応じてdataSourceKeyRW、data SourceKeyRに戻りますか?この方法は参照されていないので、springが自動的に起動するので、静的変数を用いてdataSourceのkeyを格納し、sql文を呼び出す前に静的変数の値を設定し、この方法で静的変数の値を取得して戻ることを考慮する。マルチスレッドを考慮すると、スレッド間の干渉を避けるために、threadLocalを使用することも考えられる。
まずはdata SourceKeyを格納する容器類を見ます。

public class DBContextHolder { 
  /** 
   *   threadlocal 
   */ 
  private static ThreadLocal<String> contextHolder = new ThreadLocal<>(); 
  private String DB_TYPE_RW = "dataSourceKeyRW"; 
  private String DB_TYPE_R = "dataSourceKeyR"; 
  public String getDbType() { 
    String db = contextHolder.get(); 
    if (db == null) { 
      db = DB_TYPE_RW;//        
    } 
    return db; 
  } 
  /** 
   *       dbtype 
   * @param str 
   * @see [   /  ](  ) 
   * @since [  /    ](  ) 
   */ 
  public void setDbType(String str) { 
    contextHolder.set(str); 
  } 
  /** 
   * clearDBType 
   * @Title: clearDBType 
   * @Description:        
   */ 
  public static void clearDBType() { 
    contextHolder.remove(); 
  } 
} 
ダイナミックデータソースの実装クラス。

public class DynamicDataSource extends AbstractRoutingDataSource { 
  /* 
   * (non-Javadoc) 
   * @see javax.sql.CommonDataSource#getParentLogger() 
   */ 
  @Override 
  public Logger getParentLogger() throws SQLFeatureNotSupportedException { 
    // TODO Auto-generated method stub 
    return null; 
  } 
  /** 
   * override determineCurrentLookupKey 
   * <p> 
   * Title: determineCurrentLookupKey 
   * </p> 
   * <p> 
   * Description:     datasource 
   * </p> 
   * @return 
   */ 
  @Override 
  protected Object determineCurrentLookupKey() { 
    return DBContextHolder.getDbType(); 
  } 
} 
DAO層にデータベースタイプを設定します。

/** 
   *      
   * @param sms 
   * @return 
   */ 
  public boolean insertEmail(Email email) { 
    //               
    DBContextHolder.setDbType(DBContextHolder.DB_TYPE_RW); 
    //DBContextHolder.setDbType(DBContextHolder.DB_TYPE_R); 
    int result = this.getSqlSession().insert(STATEMENT + ".addEntity", 
        email); 
    return result == 1; 
  } 
本例ではDAOでデータベースを指定しますが、必要に応じてserviceまたはcontrollerでDBタイプを指定してもいいです。覚えておきたいのはsetDbTypeはスレッド次元に対してのものです。マルチスレッドの問題を考慮します。
締め括りをつける
以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考学習価値を持ってほしいです。ありがとうございます。もっと知りたいなら、下のリンクを見てください。