最初に注意として JDK は今のところ必ず 1.8 (Java 8) を使用すること。 JDK 9.0 を使用してしまうと以下の手順の中で原因不明のエラーが表示されてしまう。 Kotlin 側のプラグインもまだ 1.8 までしか用意されていない。
まず PostgreSQL の例
Spring Boot やその他 Java EE プロジェクトでデータベースを扱う際は JPA を使用することが多いと思うが、まずここでは IntelliJ IDEA を使用し Spring Boot で PostgreSQL を使用できる環境を作る手順を示す。 新規プロジェクトの Spring Initializr の依存関係で以下を選択する:
- Web (Spring MVC)
- Thymeleaf
- JPA
- PostgreSQL
この状態でアプリケーションクラスを実行すると以下のエラーとなる:
Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified and no embedded datasource could be auto-configured.
エラーメッセージの通り application.yaml
に以下を定義する:
spring:
datasource:
url: jdbc:postgresql://localhost/postgres
driverClassName: org.postgresql.Driver
username: postgres
password: postgres
これで実行するとまたエラーとなる:
java.lang.reflect.InvocationTargetException: null
...(中略)...
Caused by: java.sql.SQLFeatureNotSupportedException: org.postgresql.jdbc.PgConnection.createClob() メソッドはまだ実装されていません。
これでは何だか分からないので Stack Overflow に聞いてみると application.yaml
に以下の設定を追加すれば良いようだ:
spring:
jpa:
properties:
hibernate:
temp:
use_jdbc_metadata_defaults: false
dialect: org.hibernate.dialect.PostgreSQLDialect
この状態で再度アプリケーションクラスを実行し、先ほどのエラーが表示されずに正しく Tomcat が起動する事を確認する。
SQLite の場合
SQLite の場合 PostgreSQLDialect
に値する SQLiteDialect
といった実装が最初から用意されていない。
ただ、これに関しては既に作成して Maven リポジトリに上げている方がいらっしゃるのでありがたく使用させていただくことにする。
それと SQLite の JDBC ドライバも必要なので build.gradle
に以下を追加する:
dependencies {
compile('com.enigmabridge:hibernate4-sqlite-dialect:0.1.2')
runtime('org.xerial:sqlite-jdbc')
}
これに従い application.yaml
を以下に書き換える:
spring:
datasource:
# SQLite のファイル位置を指定
url: jdbc:sqlite:./db.sqlite3
driverClassName: org.sqlite.JDBC
jpa:
properties:
hibernate:
temp:
use_jdbc_metadata_defaults: false
dialect: com.enigmabridge.hibernate.dialect.SQLiteDialect
アプリケーションクラスを実行し、正しく Tomcat が立ち上がることを確認する。
簡単にテストしてみる
JPA の詳細に関しては検索すればいくらでも出てくるのでここには記載しない。
まず該当するテーブルが SQLite 内にあるものとして以下のような感じで Entity
クラスを用意する:
@Entity
@Table(name = "post")
data class Post(
@Id @GeneratedValue(strategy = GenerationType.AUTO) var id: Int = 0,
var date: String = "",
var name: String = "",
var text: String = "",
var enabled: Boolean = false,
var created: Date = Date(),
var modified: Date = Date()
)
Kotlin だと data class
で Entity
が用意できるのでとても便利だ。
toString()
を実装しなくてもいい感じにクラス内のデータを出力してくれる。
var
にして意味のない初期値を与えなければならないところがちょっと格好悪いが仕方がないところだろうか。
対応する PostRepository
クラスを以下のように定義する:
interface PostRepository : JpaRepository<Post, String> {
fun findById(id: Int): Post
}
定義したリポジトリを使用してコントローラから実行してみる (本来は Service
から実行するのが筋だがここでは例のため簡単にする):
@Controller
class SampleController {
@Autowired
lateinit var postRepository: PostRepository
@GetMapping("/")
fun sample(model: Model): String {
val post = postRepository.findById(1) // ID をキーにして 1 件取得
System.out.println(post) // Post の中身が出力される
return "sample"
}
}
特に意味はないがテンプレートが必要なので /resources/templates/sample.html
として以下を用意:
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Sample</title>
</head>
<body>
<p>Hello World!!</p>
</body>
</html>
実行して http://localhost:8080
にアクセスし、標準出力に正しく DB 取得結果が表示されることを確認する。