Spring Boot環境でのSpring Data JPA 事始めメモ

こんにちは、大分ベテランになってきた職業プログラマ:older_man_tone1:です。
頑張って新しいフレームワークを学んでおりますが、難しいやら覚えられないやらで、困っています。
最近は、Qiitaのようなプログラマ情報共有サイトがあって便利になりました。学んだことをこちらで保存して、頭の中を整理をするとともに、覚えられないことを記録していこうと思います。
本日はSpring Data JPAに挑戦しました。

## Spring Data JPAのガイド

今回は3種類のガイドを参照しました。

1. [簡単なチュートリアル](https://spring.io/guides/gs/accessing-data-jpa/)
2. Spring Bootガイド の [Spring Data JPAに関係のある章](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-sql)
3. [Spring Data JPAの公式ドキュメント](https://docs.spring.io/spring-data/jpa/docs/current/reference/html/)

自分はいつも簡単なチュートリアルから始めます。1番のリンクは、Spring Bootを使ったSpring Data JPAのGetting Startedです。

続いて、設定は、2番で大体学習しました。
3番のSpring Data JPAの公式ドキュメントは、細かく調べるときだけ見ました。


## セットアップ

### Mavenの依存関係

1番のチュートリアルですと、Mavenに記載する依存関係はこの通りです。

``` xml:pom.xml
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
```

2番の公式ガイドですと[29.1.1 Embedded Database Support](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-sql)に説明されています。spring-boot-starter-data-jpa（Spring Bootを使ったSpring Data JPA）では、Bootのauto-configure機能によって、組込みデータベースが何もしなくても使えるようになっています。主に、JUnitの単体テストで使うことになると思いますが、H2かHSQLを一緒に依存関係に入れておくお作法になっているようです。



### MySQLドライバの設定

2番の公式ガイドの[29.1.2 Connection to a production database](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-connect-to-production-database)に説明があります。

``` properties:application.properties
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
```

チュートリアルやサンプルプログラムではよく『com.mysql.jdbc.Driver』という記述を見かけますが、[MySQLの公式ガイド](https://dev.mysql.com/doc/connector-j/6.0/en/connector-j-api-changes.html)によると、これは今はdeprecatedで、新しいクラス名は『com.mysql.cj.jdbc.Driver』のようです。


### JPAのDDL発行機能（※オプション）

JPA(SpringではHibernate実装)には、Beanの定義からDDLを発行できる機能があります。

> By default, JPA databases will be automatically created only if you use an embedded database (H2, HSQL or Derby)

ガイドでは、主に組込みDB向けに使われる想定の機能ですが、これをMySQLなどのデータベースサーバでも使う場合は、この機能を以下の設定でONにします。

記載の仕方は[こちら](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-creating-and-dropping-jpa-databases)に解説された通りです。

``` properties:application-junit.properties
spring.jpa.hibernate.ddl-auto=update
```
設定可能な値は、none, validate, update, create, create-dropです。
説明は、[こちら](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-initialize-a-database-using-hibernate)にあります。

Spring Bootには、起動時にschema.sqlを実行する（そして、そのsql文でテーブルを作成したりする）という機能がありますが、SQLファイルを作成するまでも無いかな？と思うところに、現時点では使ってみたりしています。ただ、production環境では、noneにして機能を止めています。

### コネクションの死活チェック

コネクションを取得する際に、コネクションがデータベースサーバと接続されていることを確認するチェック機能を有効にします。

``` properties:application.properties
spring.datasource.tomcat.test-on-borrow=true
spring.datasource.dbcp.validation-query=SELECT 1
```

### 文字化けを防ぐために
データベースやスキーマの文字コードをUTF-8に設定したあとで、アプリケーションから利用すると、日本語が文字化けしたため、SpringからMySQL間の接続（ドライバ＆コネクション）にもUTF-8を設定しました。

実際の設定がこちらです。

``` application.properties
spring.datasource.connectionProperties=useUnicode=true;characterEncoding=utf-8;
```

参考にしたStackOverFlowは[こちら](http://stackoverflow.com/questions/40250678/set-jpa-utf-8-encoding-in-application-properties)です。

IntelliJ IDEAでは、設定自体が古いという注意が出て、ガイドのどこかでもそれを示唆する記載を見たのですが、実際にこれで動作して、日本語の文字化けが治りました。

細かく考えると、このconnectionPropertiesは、（私の場合はDatasourceにTomcatを使っているので）TomcatのDatasourceからドライバに渡される値のようです。

まず、MySQLドライバ（MySQL Connector/J）への設定方法は、[公式ガイドのこちら](https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-charsets.html)に記載がありまして、どうも普通はサーバ側をUTF-8にしていればクライアント側も自動検出されるそうなのですが、クライアント側でしっかりUTF-8にしたい場合は"characterEncoding"プロパティをUTF-8に設定すべし、という感じのようです。

> To allow multiple character sets to be sent from the client, use the UTF-8 encoding, either by configuring utf8 as the default server character set, or by configuring the JDBC driver to use UTF-8 through the characterEncoding property.

なんか、少し意訳してしまいました:older_man_tone1:

さきほどのapplications.propertiesに記載したuseUnicodeとcharacterEncodingについても説明がありました。

> Prior to MySQL Server 4.1, Connector/J supported a single character encoding per connection, which could either be automatically detected from the server configuration, or could be configured by the user through the useUnicode and characterEncoding properties.

useUnicodeとcharacterEncodingの両方を記載するのは、MySQL4.1以前の設定のようですね。以降のバージョンでは、characterEncodingだけでも動作しそうです。

さて、このプロパティ値をMySQLドライバに渡すところですが、connectionPropertiesの値は、そのままTomcatのDatasourceクラスの[setConnectionPropertiesメソッド](https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/jdbc/pool/DataSourceProxy.html#setConnectionProperties(java.lang.String))に渡されていて、このメソッドのJavadocにあるように

> The properties that will be passed into Driver.connect(String, Properties) method

MySQLドライバに渡る…ようです。

ちなみに、TomcatのJDBCコネクションプールの[解説ページ](https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html#Common_Attributes)ではApache Commons DBCPとの比較表があるのですが、connectionProperties属性は、共通属性で紹介されていましたので、SpringでDatasourceとしてCommonsのDBCPを選択しても使えそうです。

## JPAを使うJavaプログラム

さて、すっかり設定ばかり記載しましたが、大分長文になってしまったので、今日はこのあたりで…Javaプログラムについては、チュートリアルの通りでしたので、ここでは割愛致します。

最近のプログラミングは自動部分が多いので、どちらかというと、設定等を確認するのに学習コストが多くなっている気がします。プログラムを書くよりも、むしろ設定が複雑になっている世界…ビット演算を書いていたころからすると、本当に隔世の感です:older_man_tone1:

設定類も、初老には難しいので、間違いや良い記述方法がありましたら、教えて頂けると有難いです。お気づきの点がありましたら、コメントをお願い致します。

では失礼いたします。