Spring bootでマルチデータソースを利用する場合の実装方法を整理します。
##Mybatisの場合
Autoconfigを利用するので、application.propertiesにDBの接続情報を記載します。
#プライマリーDB
spring.datasource.url=jdbc:mysql://localhost:3306/primary_db?useSSL=false
spring.datasource.username=demo
spring.datasource.password=demo
spring.datasource.driverClassName=com.mysql.jdbc.Driver
#セカンダリーDB
secondary.datasource.url=jdbc:mysql://localhost:3306/secondary_db?useSSL=false
secondary.datasource.username=demo
secondary.datasource.password=demo
secondary.datasource.driverClassName=com.mysql.jdbc.Driver
通常の通りにSpring bootのmainクラスを作成します。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args).close();
}
}
プライマリーdataSourceとsqlSessionを定義します。
・リポジトリクラスのbasepackage
・SQLMapの格納フォルダ
@Configuration
@MapperScan(basePackages = PrimaryDbConfig.BASE_PACKAGES
, sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryDbConfig {
public static final String BASE_PACKAGES = "com.example.demo.primary";
public static final String MAPPER_XML_PATH = "classpath:com/example/demo/primary/*.xml";
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return new DataSource();
}
@Primary
@Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource primaryDataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(primaryDataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_XML_PATH));
return bean.getObject();
}
@Bean(name = "primarySqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
上記と同様にセカンダリーdataSourceとsqlSessionを定義します。
@Configuration
@MapperScan(basePackages = SecondaryDbConfig.BASE_PACKAGES
, sqlSessionTemplateRef = "secondarySqlSessionTemplate")
public class SecondaryDbConfig {
public static final String BASE_PACKAGES = "com.example.demo.secondary";
public static final String MAPPER_XML_PATH = "classpath:com/example/demo/secondary/*.xml";
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "secondary.datasource")
public DataSource dataSource() {
return new DataSource();
}
@Bean(name = "secondarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("secondaryDataSource") DataSource secondaryDataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(secondaryDataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_XML_PATH));
return bean.getObject();
}
@Bean(name = "secondarySqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("secondarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
それぞれのリポジトリクラスを作成します。
@Mapper
public interface PrimaryRepository {
public long selectCountFromPrimary();
}
@Mapper
public interface SecondaryRepository {
public long selectCountFromSecondary();
}
以下のリソースフォルダにプライマリーのSqlMapを定義します。
com
|-example
|-demo
|-primary
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.primary.PrimaryRepository">
<select id="selectCountFromPrimary" resultType="long">
select count(*) from emp;
</select>
</mapper>
以下のリソースフォルダにセカンダリーのSqlMapを定義します。
com
|-example
|-demo
|-secondary
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.secondary.SecondaryRepository">
<select id="selectCountFromSecondary" resultType="long">
select count(*) from emp2;
</select>
</mapper>
上記リポジトリを呼び出し、SQLを実行します。
@Autowired
private PrimaryRepository primaryRepository;
@Autowired
private SecondaryRepository secondaryRepository;
...
long countPrimary = primaryRepository.selectCountFromPrimary();
long countSecondary = secondaryRepository.selectCountFromSecondary();
##Spring Data JPAの場合
Mybatisと同様にapplication.propertiesにDBの接続情報を記載します。
#プライマリーDB
spring.datasource.url=jdbc:mysql://localhost:3306/primary_db?useSSL=false
spring.datasource.username=demo
spring.datasource.password=demo
spring.datasource.driverClassName=com.mysql.jdbc.Driver
#セカンダリーDB
secondary.datasource.url=jdbc:mysql://localhost:3306/secondary_db?useSSL=false
secondary.datasource.username=demo
secondary.datasource.password=demo
secondary.datasource.driverClassName=com.mysql.jdbc.Driver
spring.jpa.database=default
通常の通りにSpring bootのmainクラスを作成します。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
プライマリーのdataSource、entityManagerとtransactionManagerを定義します。
・リポジトリクラスのbasepackage
・ドメインクラスのbasepackage
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory"
, transactionManagerRef = "transactionManager"
, basePackages = { "com.example.demo.primary" })
public class PrimaryDbConfig {
@Primary
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("dataSource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("com.example.demo.primary.domain").build();
}
@Primary
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
上記と同様にセカンダリーのdataSource、entityManagerとtransactionManagerを定義します。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "secondaryEntityManagerFactory"
, transactionManagerRef = "secondaryTransactionManager"
, basePackages = {"com.example.demo.secondary" })
public class SecondaryDbConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "secondary.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("secondaryDataSource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("com.example.demo.secondary.domain").build();
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(
@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory secondaryEntityManagerFactory) {
return new JpaTransactionManager(secondaryEntityManagerFactory);
}
}
それぞれのリポジトリクラスとドメインクラスを作成します。
@Repository
public interface PrimaryRepository extends CrudRepository<Emp, String> {
public long count();
}
@Repository
public interface SecondaryRepository extends CrudRepository<Emp2, String> {
public long count();
}
@Entity
@Table(name="emp")
public class Emp {
@Id
@Column(name="emp_id")
private String empId;
@Column(name="dept_id")
private String deptId;
...
}
@Entity
@Table(name="emp2")
public class Emp2 {
@Id
@Column(name="emp_id")
private String empId;
@Column(name="dept_id")
private String deptId;
...
Mybatisと同じの感じてリポジトリクラスを呼び出します。
@Autowired
private PrimaryRepository primaryRepository;
@Autowired
private SecondaryRepository secondaryRepository;
...
long countPrimary = primaryRepository.selectCountFromPrimary();
long countSecondary = secondaryRepository.selectCountFromSecondary();