2日前に、JdbcTemplateのマルチデータソース構成とSpring Data JPAのマルチデータソース構成を紹介しました。次に、MyBatisを使用する場合のマルチデータソースシナリオの構成方法について説明します。
複数のデータソースの構成を追加します
まず、Spring Boot構成ファイルapplication.propertiesでリンクする2つのデータベース構成を、次のように設定します。
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
説明と注意:
- 複数のデータソースを構成する場合、単一のデータソースとの違いは、spring.datasourceの後に、異なるデータソース構成を区別するために、プライマリとセカンダリのデータソース名がもう1つ設定されることです。このプレフィックスは、データソースの後続の初期化で使用されます。
- データソース接続構成2.xと1.xの構成項目は異なります。2.xはspring.datasource.secondary.jdbc-urlを使用し、1.xバージョンはspring.datasource.secondary.urlを使用します。このエラーが発生した場合java.lang.IllegalArgumentException:構成中にdriverClassName。でjdbcUrlが必要な場合は、この構成アイテムの問題です。
- どのデータアクセスフレームワークを使用しても、データソースの構成は同じであることがわかります。
データソースとMyBatis構成を初期化します
複数のデータソースの構成情報を完成させたら、構成クラスを作成して構成情報をロードし、データソースを初期化し、各データソースのMyBatis構成を初期化します。
ここでは、データソースとフレームワークの構成を引き続き分割します。
- 次のように、複数のデータソース用に個別の構成クラスを作成します。
@Configuration
public class DataSourceConfiguration {
@Primary
@Bean
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
内容はJdbcTemplateおよびSpringDataJPAとまったく同じであることがわかります。@ConfigurationProperties
これら2つのデータソースがロードされていることを知ることができるコンフィギュレーションのをspring.datasource.primary.*
し、それぞれspring.datasource.secondary.*
。@Primary
注釈はメインデータソースを指定します。つまり、どのデータソースを指定しない場合、このBeanの実際の違いが次のJPA構成で使用されます。
- 2つのデータソースのMyBatis構成をそれぞれ作成します。
プライマリデータソースのJPA構成:
@Configuration
@MapperScan(
basePackages = "com.didispace.chapter39.p",
sqlSessionFactoryRef = "sqlSessionFactoryPrimary",
sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
public class PrimaryConfig {
private DataSource primaryDataSource;
public PrimaryConfig(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
this.primaryDataSource = primaryDataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(primaryDataSource);
return bean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {
return new SqlSessionTemplate(sqlSessionFactoryPrimary());
}
}
セカンダリデータソースのJPA構成:
@Configuration
@MapperScan(
basePackages = "com.didispace.chapter39.s",
sqlSessionFactoryRef = "sqlSessionFactorySecondary",
sqlSessionTemplateRef = "sqlSessionTemplateSecondary")
public class SecondaryConfig {
private DataSource secondaryDataSource;
public SecondaryConfig(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
this.secondaryDataSource = secondaryDataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactorySecondary() throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(secondaryDataSource);
return bean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplateSecondary() throws Exception {
return new SqlSessionTemplate(sqlSessionFactorySecondary());
}
}
説明と注意:
@MapperScan
注釈は、現在のデータソースで定義されているエンティティとマッパーのパッケージパスを指定するために構成クラスで使用されます。さらに、sqlSessionFactoryとsqlSessionTemplateを指定する必要があります。これら2つの特定の実装は、構成クラスで初期化されます。- 構成クラスのコンストラクターでは、
@Qualifier
注釈を使用して使用するデータソースを指定します。その名前は、DataSourceConfiguration
構成クラスのデータソースによって定義された関数名に対応します。 - 構成クラスでSqlSessionFactoryとSqlSessionTemplateの実装を定義し、使用されている正しいデータソースに注意してください(ここでデモコードを使用する場合、2番目の手順に問題がない限り、変更する必要はありません)。
前回の記事でJPAを紹介したとき、JPAの使い方を紹介したときに、エンティティとリポジトリの定義方法について触れたので、ユーザーとリポジトリの定義コードを省略しましたが、なぜそうならないのかと聞かれる方もいらっしゃいます。コードにもあります。もう一度そのような質問をすることを避けていないので、ここに投稿してください。
上記のプライマリデータソースの定義に従って、com.didispace.chapter39.p
パッケージの下で、次のように、プライマリデータソースによって使用されるエンティティとデータアクセスオブジェクトを定義します。
@Data
@NoArgsConstructor
public class UserPrimary {
private Long id;
private String name;
private Integer age;
public UserPrimary(String name, Integer age) {
this.name = name;
this.age = age;
}
}
public interface UserMapperPrimary {
@Select("SELECT * FROM USER WHERE NAME = #{name}")
UserPrimary findByName(@Param("name") String name);
@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
int insert(@Param("name") String name, @Param("age") Integer age);
@Delete("DELETE FROM USER")
int deleteAll();
}
上記のセカンダリデータソースの定義に従って、com.didispace.chapter39.s
パッケージの下で、次のように、セカンダリデータソースによって使用されるエンティティとデータアクセスオブジェクトを定義します。
@Data
@NoArgsConstructor
public class UserSecondary {
private Long id;
private String name;
private Integer age;
public UserSecondary(String name, Integer age) {
this.name = name;
this.age = age;
}
}
public interface UserMapperSecondary {
@Select("SELECT * FROM USER WHERE NAME = #{name}")
UserSecondary findByName(@Param("name") String name);
@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")
int insert(@Param("name") String name, @Param("age") Integer age);
@Delete("DELETE FROM USER")
int deleteAll();
}
テスト検証
上記を完了した後、上記の複数のデータソース構成が正しいかどうかを試すためのテストクラスを作成し、最初に検証のアイデアを設計します。
- プライマリデータソースにデータを挿入します
- プライマリデータソースから挿入されたばかりのデータをクエリし、構成が正しいかどうかをクエリできます
- セカンダリデータソースから挿入されたばかりのデータをクエリします。構成が正しい場合は、クエリしないでください。
- データの一部をセカンダリデータソースに挿入します
- プライマリデータソースから挿入されたばかりのデータをクエリします。構成が正しい場合は、クエリしないでください。
- セカンダリデータソースから挿入されたばかりのデータをクエリし、構成が正しいかどうかをクエリできます
具体的な実装は次のとおりです。
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class Chapter39ApplicationTests {
@Autowired
private UserMapperPrimary userMapperPrimary;
@Autowired
private UserMapperSecondary userMapperSecondary;
@Before
public void setUp() {
// 清空测试表,保证每次结果一样
userMapperPrimary.deleteAll();
userMapperSecondary.deleteAll();
}
@Test
public void test() throws Exception {
// 往Primary数据源插入一条数据
userMapperPrimary.insert("AAA", 20);
// 从Primary数据源查询刚才插入的数据,配置正确就可以查询到
UserPrimary userPrimary = userMapperPrimary.findByName("AAA");
Assert.assertEquals(20, userPrimary.getAge().intValue());
// 从Secondary数据源查询刚才插入的数据,配置正确应该是查询不到的
UserSecondary userSecondary = userMapperSecondary.findByName("AAA");
Assert.assertNull(userSecondary);
// 往Secondary数据源插入一条数据
userMapperSecondary.insert("BBB", 20);
// 从Primary数据源查询刚才插入的数据,配置正确应该是查询不到的
userPrimary = userMapperPrimary.findByName("BBB");
Assert.assertNull(userPrimary);
// 从Secondary数据源查询刚才插入的数据,配置正确就可以查询到
userSecondary = userMapperSecondary.findByName("BBB");
Assert.assertEquals(20, userSecondary.getAge().intValue());
}
}
コード例
この記事の関連する例については、次のウェアハウスのchapter3-9
ディレクトリを表示できます。
- Github:https://github.com/dyc87112/SpringBoot-Learning/
- Gitee:https://gitee.com/didispace/SpringBoot-Learning/
この記事が良いと思うなら、スターのサポートを歓迎します。あなたの注意が私の粘り強さの動機です!
この記事が最初に公開されました:Spring Boot 2.xの基本チュートリアル:MyBatisの複数のデータソース構成
、再印刷のソースを指定してください。
私の公式アカウントであるProgramApe DDに注目してください。独占的な学習リソースと、毎日の乾物のプッシュを入手できます。
私の他のトピックに興味がある場合は、私の個人的なブログであるdidispace.comに直接アクセスしてください。