Kotlin Springboot -- Part 22 JPA で Postgres DB とつなぐ
Tags: kotlin, ca
Published: 2022-12-22 17:12:09


## JPA の依存性の確認。

まず親のモジュールにいれる。

現状、親の gradle の依存ファイルは

```kotlin
plugins {
	id("org.springframework.boot") version "2.7.2"
	id("io.spring.dependency-management") version "1.0.12.RELEASE"
	kotlin("jvm") version "1.6.21"
	kotlin("plugin.spring") version "1.6.21"
	kotlin("plugin.jpa") version "1.6.21"
	kotlin("plugin.allopen") version "1.6.21"
}
```

既に JPA のプラグイン入っており

```kotlin
dependencies {
	implementation("org.springframework.boot:spring-boot-starter-data-jpa")
	implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
	implementation("org.springframework.boot:spring-boot-starter-web")
	implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
	implementation("org.jetbrains.kotlin:kotlin-reflect")
	implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
	implementation ("com.google.code.gson:gson:2.9.1")
	runtimeOnly("com.h2database:h2")
	testImplementation("org.springframework.boot:spring-boot-starter-test")
	testImplementation("org.amshove.kluent:kluent:1.68")
```


* spring boot starter jpa
* reflect
* stdlib-jdk8

公式で必要とされるこれらがはいっていた。

https://www.javadrive.jp/start/install/index5.html#section4

記事では jdk を使えと書いてあった。
しかし、jdk は jre を含むので大丈夫。

これに依存性として postgres を追加 

https://github.com/DioPires/kotlin-spring-postgres-example/blob/master/build.gradle.kts

```kotlin
	runtimeOnly("org.postgresql:postgresql")
```

また、postgres を追加

---

## postgres DB サーバーの作成とテーブルの生成

https://dev.to/kaede_io/sql-ji-chu-part-04-docker-compose-deli-tetakontenade-db-sabali-tishang-geshi-niteburuwozuo-ru-3ia5

docker-compose で作った

person テーブルで name と age のみ。
これだと SQL ではエラーを出さない。
しかしフレームワークでエラーを出すので後ほど ID をいれた。

---

## postgres の読み込み先を追加

https://intellectual-curiosity.tokyo/2019/04/21/spring-boot%E3%81%A7%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/#applicationproperties

同様にこのサイトを参考にして

application.properties というファイルを作成

```kotlin
spring.datasource.url=jdbc:postgresq//localhost:5444/person
spring.datasource.username=kaede
spring.datasource.password=pass
spring.jpa.generate-ddl=true
```

https ではなく、jbdc で URL を書き、DB 名を書く
localhost:5444/person
に今回はなる。ポート指定がないと 5432 になるようだ。

ルートユーザーとパスを書く

---

## Driver に JPA と Postgres の依存を追加

Root 同様、Driver の build.gradle.kts にも JPA の dependencies を入れる。

```kotlin
dependencies {
// ...
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    runtimeOnly("org.postgresql:postgresql")
}
```

spring...jpa と postgres をいれた。

---

## PersonTableEntity.kt を作成

既存の PersonEntity.kt というファイルがあるので
かぶりを避けるために PersonTableEntity.kt にした。

```kotlin
package com.kaede

import javax.persistence.*

@Entity
@Table(name="person")
data class PersonTableEntity(
    @Id
    @Column(name = "id", nullable = false)
    open val id: Int? = null,
    @Column(name = "name", nullable = false)
    open val name: String? = null,
    @Column(name = "age", nullable = false)
    open val age: Int? = null
)
```

persistence でここのアノテーションを使えるようにする。
ID がないとエラーになる。
なので DB にも追加してきた。

最初に無理に null 定義している？ようにみえる。 open val のところはよくわかっていない。

---

## PersonTableDriver.kt を作成

PersonTableEntity と同様の理由で
Table を中に挟んで PersonDriver と別ファイルで作成した。

別のところから取る Driver だから当たり前か。

```kotlin
package com.kaede

import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Component

@Component
interface PersonTableDriver: JpaRepository<PersonTableEntity, Int>
```

Jpa リポジトリは、エンティティとリンクさせて interface でかく。
すると中の save, saveAll, findAll, などが呼び出せる。

クラスは作らない。

---

## Gateway で呼び出し

```kotlin
@Component
class PersonGateway() : PersonPort { // Port の関数を実装するから
    @Autowired
    lateinit var personDriver: PersonDriver
    @Autowired
    lateinit var personTableDriver: PersonTableDriver
    override fun getAllPersons(): Persons {
        val personTable = personTableDriver.findAll()
        println(personTable);
        val personsEntity = personDriver.findAll()
        val personsDomain= personsEntity.map { personEntity ->
            Person(Name(personEntity.name), Age(personEntity.age))
        }
        return Persons(personsDomain)
    }
```

既存の Gateway で DI に追加して
findAll を呼び出して print してみた。

PersonApiApplication を実行すると

```php
2022-12-23 02:00:51.601  INFO 3269431
 --- [           main] com.kaede.PersonApiApplicationKt
         
: Started PersonApiApplicationKt in 2.304 seconds 
(JVM running for 2.682)

[PersonTableEntity(id=1, name=Taro, age=5), 
PersonTableEntity(id=2, name=Hana, age=3)]
```

このように、DB に入れた中身が引き出せた！！！