Spring BootとJPAで複数データベースを扱う実装方法




複数データベースを扱う方法

Spring BootとJPAで1つのデータベースを扱うのはサンプルも豊富なので簡単ですが、複数となると一気にサンプルが減り、なかなか実現するのが大変でした。なので、MySQLとPostgreSQLの2つに接続できる設定と実装方法を紹介します。

application.properties

application.propertiesに2つのデータベースへの接続設定を記載します。

spring:
  datasource:
    mysql:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/sample
      username: user
      password: pass
    postgres:
      driver-class-name: org.postgresql.Driver
      url: jdbc:postgresql://localhost:5432/sample
      username: user
      password: pass

接続処理

まずMySQLの接続処理を行うクラスです。

/**
 * MySQL Database Config
 */
@Component
@ConfigurationProperties(prefix = "spring.datasource.mysql")
@EnableJpaRepositories(
        basePackages=arrayOf("com.sample.repository.mysql"),
        entityManagerFactoryRef="mysqlEntityManagerFactory"
)
class MySqlDatabaseConfig {

    var driverClassName: String = ""

    var url: String = ""

    var username: String = ""

    var password: String = ""

    @Primary
    @Bean("mysqlDataSource")
    fun dataSource(): DataSource {
        val dataSource: DriverManagerDataSource = DriverManagerDataSource()
        dataSource.setDriverClassName(driverClassName)
        dataSource.setUrl(url)
        dataSource.setUsername(username)
        dataSource.setPassword(password)
        return dataSource
    }

    @Primary
    @Bean("mysqlEntityManagerFactory")
    fun entityManagerFactory(@Qualifier("mysqlDataSource") dataSource: DataSource): EntityManagerFactory {
        val factory: LocalContainerEntityManagerFactoryBean = LocalContainerEntityManagerFactoryBean()
        factory.setDataSource(dataSource)
        factory.setPackagesToScan("com.sample.entity.mysql",)

        val vendorAdapter: HibernateJpaVendorAdapter = HibernateJpaVendorAdapter()
        factory.setJpaVendorAdapter(vendorAdapter)
        factory.afterPropertiesSet()

        return factory.getObject()
    }
}

DriverManagerDataSourceはコネクションプールの機能がないので本番環境で使用しないようにしてください。コネクションプールの設定はHikariCPがオススメなので下記記事を参考にしてください。

関連記事:Spring BootでHikariCPを使ってコネクションプールを設定する方法

次にPostgreSQLです。

/**
 * PstgreSQL Database Config
 */
@Component
@ConfigurationProperties(prefix = "spring.datasource.postgres")
@EnableJpaRepositories(
        basePackages=arrayOf("com.sample.repository.postgres"),
        entityManagerFactoryRef="postgresEntityManagerFactory"
)
class PostgresDatabaseConfig {

    var driverClassName: String = ""

    var url: String = ""

    var username: String = ""

    var password: String = ""

    @Bean("postgresDataSource")
    fun dataSource(): DataSource {
        val dataSource: DriverManagerDataSource = DriverManagerDataSource()
        dataSource.setDriverClassName(driverClassName)
        dataSource.setUrl(url)
        dataSource.setUsername(username)
        dataSource.setPassword(password)
        return dataSource
    }

    @Bean("postgresEntityManagerFactory")
    fun entityManagerFactory(@Qualifier("postgresDataSource") dataSource: DataSource): EntityManagerFactory {
        val factory: LocalContainerEntityManagerFactoryBean = LocalContainerEntityManagerFactoryBean()
        factory.setDataSource(dataSource)
        factory.setPackagesToScan("com.sample.entity.postgres")

        val properties: Properties = Properties()
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect")

        val vendorAdapter: HibernateJpaVendorAdapter = HibernateJpaVendorAdapter()
        factory.setJpaVendorAdapter(vendorAdapter)
        factory.setJpaProperties(properties)
        factory.afterPropertiesSet()

        return factory.getObject()
    }
}

違いは2箇所で、MySQLの方に@Primaryをつけているのと、PostgreSQLの方はPropertiesを使ってdialectを指定しています。

@ConfigurationPropertiesにapplication.propertiesに設定した各データベース設定のルートパスを指定すると同名のメンバ変数に値を代入することができます。

@EnableJpaRepositoriesにはrepositoryのパッケージ名とEntityManagerFactoryのBean名を設定します。

MySQLとPostgreSQLのEntityとRepositoryは上記設定を行いやすくするためにも分けるようにしておいてください。

また、PostgreSQLのDriverを変更するだけでAWS Redshiftも扱えるようになります。下記リンクを参考にしてみてください。

GradleでRedshift JDBC Driverの取得と設定方法

使用方法

カスタムインターフェースを実装するときのみ変更が必要になります。カスタムインターフェースの実装方法は下記リンクを参照してください。

Spring Data JPAでカスタムRepositoryインターフェースを実装する方法

class SampleRepositoryImpl @Autowired constructor(@Qualifier("mysqlEntityManagerFactory") val emf: EntityManagerFactory) : SampleRepositoryCustom {

    /**
     * 期間を指定して取得
     *
     * @param appIds ID
     * @return サンプルリスト
     */
    override fun findById(id: Int): List<SampleEntity> {
        val sql: String = """
                            SELECT
                                *
                            FROM
                                sample
                            WHERE
                                id  :id
                          """

        val em: EntityManager = emf.createEntityManager()
        val query: Query = em.createNativeQuery(sql, "Sample")
            .setParameter("id", id)

        return query.getResultList() as List<SampleEntity>
    }
}

設定箇所が少し多いですが上記を参考に実装していただければと思います。

最後にSpring Boot関連の記事を以下にまとめましたのでこちらも是非読んでください。

おすすめ書籍

JPAに関して体系的に学べる良い書籍だと思います。良くあるSpring系書籍ですとJPAは少ししか紹介がありませんが丸々一冊JPAに関してなので詳細な解説がされています。内容はJPAと他のORMとの比較から始まりセットアップ、実装の仕方まで幅広く網羅されています。これからJPAで開発を初めてみようかなと考えている方は一読することをオススメします!

 
Springの概要からインストール方法、各コア機能(Security, Sessionなど)の解説が体系的にまとめられています。2018年に出版されたばかりなので情報も新しいです。これからSpring Bootでアプリケーション開発をしたい方の最初に読む一冊としておすすめします。対象は初心者だけでなく上級者まで幅広く学べるので是非読んでみてください!

 

The following two tabs change content below.

髙妻智一

2013年CyberAgent新卒入社 スマホゲームを作る子会社に所属し、サーバーサイドのエンジニアを担当。2年目の終わりから新規子会社の立ち上げに参加し、サーバーサイドのエンジニアリーダーとしてサービースのリリースから運用までを担当。 2018年仮想通貨のスマホウォレットを提供するGinco Incにブロックチェーンエンジニアとして入社。






よく読まれている関連記事はこちら



コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です