こんな感じのことをします。(察して...)
DB アクセスのエッセンスに注目したかったので、 CLI アプリとして作ります。
環境
OS: Windows 10 Pro
Java: openjdk version "11" 2018-09-25
Docker: Docker version 18.06.1-ce, build e68fc7a
依存定義
次の jar を依存関係として定義した。
Java9(11?) からの変更の影響により、 jaxb-api
と javassist
を明示的に追加する必要が出てきたらしい。
dependencies {
compile("org.springframework.boot:spring-boot-starter:2.0.5.RELEASE")
compile('org.springframework.boot:spring-boot-starter-data-jpa:2.0.5.RELEASE')
runtime('org.postgresql:postgresql')
// https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api
compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
// https://mvnrepository.com/artifact/org.javassist/javassist
compile group: 'org.javassist', name: 'javassist', version: '3.23.1-GA'
}
PostgreSQL 環境の構築
構成
サーバー: PostgreSQL
DB: postgres
こんな感じで構築する。
List of relations
Schema | Name | Type | Owner
--------+----------------+----------+----------
public | message | table | postgres
public | message_id_seq | sequence | postgres
(2 rows)
Table "public.message"
Column | Type | Collation | Nullable | Defaul
t
---------+------------------------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('message_id_seq'::regclass)
message | character varying(255) | | not null |
Indexes:
"message_pkey" PRIMARY KEY, btree (id)
環境を作る
Docker オフィシャルの PostgreSQL イメージを使って作成する。
Docker オフィシャルの PostgreSQL イメージは、コンテナ起動時に指定した sql を実行する機能があるので、その仕組みを使ってデータを入れる。
初期データ作成 sql
$(pwd)/schema/schema.sql
を作成。
DROP TABLE IF EXISTS message;
DROP SEQUENCE IF EXISTS message_id_seq;
CREATE SEQUENCE message_id_seq START WITH 1 INCREMENT BY 1 ;
CREATE TABLE message (
id INTEGER DEFAULT nextval('message_id_seq' ) PRIMARY KEY ,
message VARCHAR (255 ) NOT NULL
);
INSERT INTO message(message)
VALUES
('テスト1' ),
('テスト2' );
コンテナ起動 + データ作成
次のコマンドで、 PostgreSQL サーバー起動と、前述の初期データの作成が完了する。
docker run -it --rm --name postgres -v "$(pwd)/schema:/docker-entrypoint-initdb.d" -p 5432:5432 postgres
プログラミング
エンティティの作成
まず、 DB から取得するレコードを表す Bean を作成する。
今回は、 id
と message
を取得したいので、それらをフィールドに持つ Bean を作る
アノテーション @Entity
を付ける
プライマリキーに @Id
アノテーションを付ける
id
はシーケンスによる自動採番なので、それ関係のアノテーションを付ける
@SequenceGenerator
@GeneratedValue
package gs.postgres;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
/**
* Message
*/
@Entity
@SequenceGenerator (name = "message_id_seq" , sequenceName = "message_id_seq" , allocationSize = 1 , initialValue = 1 )
public class Message {
@Id
@GeneratedValue (generator="message_id_seq" )
private Long id;
private String message;
public Long getId () {
return this .id ;
}
public void setId (Long id) {
this .id = id;
}
public String getMessage () {
return this .message ;
}
public void setMessage (String message) {
this .message = message;
}
@Override
public String toString () {
return String .format ("id: %d , message= %s " , this .id , this .message );
}
}
リポジトリインターフェースを作成
DB への操作を抽象化してくれるやつを作る。
JpaRepository
を継承したインターフェース定義だけ定義すれば、 Spring が良しなに実装を作ってくれるらしい。
継承する JpaRepository
は、 JpaRepository<エンティティの型, エンティティのプライマリキーの型>
とする。
package gs.postgres;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* MessageRepository
*/
public interface MessageRepository extends JpaRepository<Message, Long > {
}
DB にアクセスするプログラムを作る
情報取得と挿入、標準出力するプログラムを作成する。
repo
フィールドに @Autowired
アノテーションを付けているため、 Spring によって自動で MessageRepository
のインスタンス化と代入が行われる。
MessageRepository
は、SpringApplication.run(App.class, args)
をした時点で、よしなに実装が作られるみたい
repo
は JpaRepository (Spring Data JPA 2.1.0.RELEASE API) のインターフェースが実装されているので、これを使って DB 操作ができる
package gs.postgres;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.domain.Sort;
@SpringBootApplication
public class App implements CommandLineRunner {
// `SpringApplication.run` で実行した時点で、
// よしなに `MessageRepository` クラスが注入されるらしい。
@Autowired
private MessageRepository repo;
public static void main (String [] args) {
SpringApplication.run (App.class , args);
}
/**
* App 主処理
*
* 1. メッセージを全件取得して標準出力
* 2. メッセージインサート
* 3. メッセージを全件取得して標準出力
*
*/
@Override
public void run (String ... args) {
// DB(postgres/message) から全件取得する
List <Message> messages1 = repo.findAll (new Sort (Sort.Direction .ASC , "id" ));
// 取得した全件標準出力
for (Message message : messages1) {
System .out .println (message);
}
// 新規メッセージのインサート
// ID はシーケンスからの自動採番なので null のままで良い
Message insertMessage = new Message ();
insertMessage.setMessage ("インサートメッセージ" );
repo.save (insertMessage);
System .out .println ("Message added." );
// もう一度全件取得する
List <Message> messages2 = repo.findAll (new Sort (Sort.Direction .ASC , "id" ));
// 取得した全件標準出力
for (Message message : messages2) {
System .out .println (message);
}
}
}
アプリの設定
src/main/resources
に application.properties
と hibernate.properties
を作成する。
application.properties
PostgreSQL に接続するための情報を記述。
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=
hibernate.properties
hibernate.properties
はこのエラー対策
hibernate.jdbc.lob.non_contextual_creation = true
動作確認
ここまで作ったらあとは gradle run
するだけ。
gradle run
以下のような感じで取得とインサートが出来ていることが確認できる。
> gradle run
> Task :run
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.5.RELEASE)
...(略)...
2018-10-14 14:36:00.877 INFO 25552 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
id:1, message=テスト1
id:2, message=テスト2
Message added.
id:1, message=テスト1
id:2, message=テスト2
id:3, message=インサートメッセージ
...(略)...
2018-10-14 14:36:01.047 INFO 25552 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
BUILD SUCCESSFUL in 5s
3 actionable tasks: 1 executed, 2 up-to-date
完成品はこちら 。
以上。
参考資料