SpringBoot構成読み書き分離
24982 ワード
前言
このケースは、MySQLマスターの構成に基づいて行われます.
1.まずアプリケーション.propertiesで2つのデータソースを構成
SpringBootで自動的に構成されたdataSorceを使用する必要はなく、名前に注意してください.
2.DataSourceの構成クラスの作成
ここで、
3.クラス実装AbstractRoutingDataSourcelクラスをカスタマイズし、書き換え方法
この方法では、DataSourceContextは、現在のスレッドにバインドされたデータソース名をカプセル化したクラスであり、データソースの設定とデータソースの取得は、このスレッドで異なる時点で動作するため、ThreadLocalを使用して動作する
4.このルーティングを設定するdataSource
プロジェクトを開始すると、エラーが表示され、プロジェクトの開始にループが発生したと言います.
これはコンフィギュレーションクラスが独自のdataSourceを自動的に使用するコンフィギュレーションです.この場合、この自動コンフィギュレーションクラスの使用を手動でキャンセルする必要があります.
5.関連するすべてのSpringApplication構成クラスでdataSourceの自動構成を解除する
この時プロジェクトを起動して、またエラーが発生して、報告したのは
このプロジェクトはトランザクションを使用しているため、プライマリdatasourceが何であるかは指定されていません(datasource自動構成がキャンセルされているため)、トランザクションを設定する必要があります.
6.SpringBootマルチデータソースの場合、トランザクションの構成方式一:メインbean を設定する方式2:PlatformTransactionManagerのbeanを独自に構成し、dataSource をインポート
このときConfigur起動クラスの構成コードを貼り付ける
これによりSpringBootのマスタースレーブの構成が整うようになり、このときリクエストごとにスレーブデータベースが使用されているわけではなく、DataSourceContext.setはサービスに設定されており、トランザクションを使用する場合、setの前にデータソースの名前をgetしますが、この場合名前は空です(
7.AoPを使用してdatasourceを制御する
サービスでdatasourceを設定すると、使用するdatasourceがデフォルトであり、自分が使用したいデータソースではないため、aopプリエンハンスメントを使用して操作し、DataContextを変更する
このケースは、MySQLマスターの構成に基づいて行われます.
1.まずアプリケーション.propertiesで2つのデータソースを構成
SpringBootで自動的に構成されたdataSorceを使用する必要はなく、名前に注意してください.
spring.master.username=root
spring.master.password=admin
spring.master.url=jdbc:mysql:///MS
spring.master.driver-class-name=com.mysql.jdbc.Driver
spring.slave1.username=root
spring.slave1.password=
spring.slave1.url=jdbc:mysql://localhost:3307/MS
spring.slave1.driver-class-name=com.mysql.jdbc.Driver
2.DataSourceの構成クラスの作成
@ConfigurationProperties
ラベルを使用して構成情報を読み取り、接続プールオブジェクトを作成します.@Bean
@ConfigurationProperties(prefix = "spring.master")
public DataSource masterds(){
return new DruidDataSource();
}
@Bean
@ConfigurationProperties(prefix = "spring.slave1")
public DataSource slaveds(){
return new DruidDataSource();
}
ここで、
new DruidDataSource()
ではなく、DataSourceBuilder.create().build()
でdataSourceオブジェクトを作成してもよい.この場合、urlをjdbc-url
に構成し、dataSourceのtype
を構成する必要があることに注意する.3.クラス実装AbstractRoutingDataSourcelクラスをカスタマイズし、書き換え方法
public class MSRoutingDataSource extends AbstractRoutingDataSource {
/*
* key , DataSource DataSource , , DataSource
* */
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContext.getDataSource();
}
}
この方法では、DataSourceContextは、現在のスレッドにバインドされたデータソース名をカプセル化したクラスであり、データソースの設定とデータソースの取得は、このスレッドで異なる時点で動作するため、ThreadLocalを使用して動作する
@Component
public class DataSourceContext {
// ThreadLocal ,
private static ThreadLocal<String> dataSourcePool = new ThreadLocal<>();
public static String getDataSource() {
return dataSourcePool.get();
}
public static void setDataSource() {
dataSourcePool.set("slaveds");
}
}
4.このルーティングを設定するdataSource
@Bean
public MSRoutingDataSource dataSource(@Qualifier("masterds") DataSource masterds,
@Qualifier("slaveds") DataSource slaveds){
MSRoutingDataSource routingDataSource = new MSRoutingDataSource();
Map<Object,Object> targetDataSources = new HashMap<>();
targetDataSources.put("masterds",masterds);
targetDataSources.put("slaveds",slaveds);
routingDataSource.setDefaultTargetDataSource(masterds);
routingDataSource.setTargetDataSources(targetDataSources);
return routingDataSource;
}
プロジェクトを開始すると、エラーが表示され、プロジェクトの開始にループが発生したと言います.
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
basicInfoController (field private cn.kiring.ms.base.service.IUserInfoService cn.kiring.ms.base.controller.BasicInfoController.userInfoService)
↓
userInfoServiceImpl (field private cn.kiring.ms.base.mapper.UserInfoMapper cn.kiring.ms.base.service.impl.UserInfoServiceImpl.userInfoMapper)
↓
userInfoMapper defined in file [F:\JavaAc\Idea\ms\ms-parent\ms-core\target\classes\cn\kiring\ms\base\mapper\UserInfoMapper.class]
↓
sqlSessionFactory defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]
┌─────┐
| dataSource defined in class path resource [cn/kiring/ms/ApplicationCoreConfig.class]
↑ ↓
| masterds defined in class path resource [cn/kiring/ms/ApplicationCoreConfig.class]
↑ ↓
| org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker
これはコンフィギュレーションクラスが独自のdataSourceを自動的に使用するコンフィギュレーションです.この場合、この自動コンフィギュレーションクラスの使用を手動でキャンセルする必要があります.
5.関連するすべてのSpringApplication構成クラスでdataSourceの自動構成を解除する
// SpringBootApplication exclude
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
この時プロジェクトを起動して、またエラーが発生して、報告したのは
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean of type 'org.springframework.transaction.PlatformTransactionManager' that could not be found.
- Bean method 'transactionManager' not loaded because @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) did not find a primary bean from beans 'slaveds', 'masterds', 'dataSource'
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.transaction.PlatformTransactionManager' in your configuration.
このプロジェクトはトランザクションを使用しているため、プライマリdatasourceが何であるかは指定されていません(datasource自動構成がキャンセルされているため)、トランザクションを設定する必要があります.
6.SpringBootマルチデータソースの場合、トランザクションの構成
// MSRoutingDataSourced bean @Primary
@Bean
@Primary
public MSRoutingDataSource dataSource(@Qualifier("masterds") DataSource masterds,
@Qualifier("slaveds") DataSource slaveds){
MSRoutingDataSource routingDataSource = new MSRoutingDataSource();
Map<Object,Object> targetDataSources = new HashMap<>();
targetDataSources.put("masterds",masterds);
targetDataSources.put("slaveds",slaveds);
routingDataSource.setDefaultTargetDataSource(masterds);
routingDataSource.setTargetDataSources(targetDataSources);
return routingDataSource;
}
@Bean
public PlatformTransactionManager platformTransactionManager(MSRoutingDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);//
}
このときConfigur起動クラスの構成コードを貼り付ける
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@EnableTransactionManagement
@MapperScan(basePackages = "cn.kiring.ms.*.mapper")
public class ApplicationCoreConfig {
@Bean
@ConfigurationProperties(prefix = "spring.master")
public DataSource masterds(){
return new DruidDataSource();
}
@Bean
@ConfigurationProperties(prefix = "spring.slave1")
public DataSource slaveds(){
return new DruidDataSource();
}
@Bean
public MSRoutingDataSource dataSource(@Qualifier("masterds") DataSource masterds,
@Qualifier("slaveds") DataSource slaveds){
MSRoutingDataSource routingDataSource = new MSRoutingDataSource();
Map<Object,Object> targetDataSources = new HashMap<>();
targetDataSources.put("masterds",masterds);
targetDataSources.put("slaveds",slaveds);
routingDataSource.setDefaultTargetDataSource(masterds);
routingDataSource.setTargetDataSources(targetDataSources);
return routingDataSource;
}
@Bean
public PlatformTransactionManager platformTransactionManager(MSRoutingDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);//
}
}
これによりSpringBootのマスタースレーブの構成が整うようになり、このときリクエストごとにスレーブデータベースが使用されているわけではなく、DataSourceContext.setはサービスに設定されており、トランザクションを使用する場合、setの前にデータソースの名前をgetしますが、この場合名前は空です(
, @Transaction , determineCurrentLookupKey
)ので、プライマリ(デフォルト)データベースアクセスがメイン(デフォルト)です.7.AoPを使用してdatasourceを制御する
サービスでdatasourceを設定すると、使用するdatasourceがデフォルトであり、自分が使用したいデータソースではないため、aopプリエンハンスメントを使用して操作し、DataContextを変更する
public class DataSourceContext {
@Pointcut("execution(* cn.kiring.ms.base.service.impl.IpLogServiceImpl.query(..))")
public void routingPoint(){}
private static ThreadLocal<String> dataSourcePool = new ThreadLocal<>();
public static String getDataSource() {
return dataSourcePool.get();
}
@Before("routingPoint()")
public static void setDataSource() {
dataSourcePool.set("slaveds");
}
}