SpringbootとpostgreSQLを接続してデータ取得してみる

### 概要
前回VPSで建てたpostgreSQLとspringbootを接続してデータを取得してみる。

### 環境
- Springboot 3.0.5
- WIndows 11
- postgreSQL 14
- centOS 7.9

### 手順
#### 1. localでVPS上のpostgreSQLに接続してデータを挿入-確認までやってみる
##### 1. 前回記事をやっていない場合は一旦ここの手順を実施する
- https://qiita.com/eHZ/items/5151281ab45e657490dc

##### 2. WindowsでVPSのpostgreSQLに接続
```
psql -h {VPSのIPアドレス}  -U {ユーザー設定で作成したユーザー名} -d {ユーザー設定で作成したDB名}
```

##### 3. TABLEの作成
```
create table {新規テーブル名} (id serial, name VARCHAR(60));
```
以下のコマンドでテーブルが作成できたか確認
```
\dt
```

##### 4. データの登録
作成したTABLEにデータを登録する。
```
insert into {TABLE名}(name) values ('山田'), ('長田'), ('田中');
```
※ `id serial`は自動で番号が付けられるid
`INSERT 0 3`と表示されれば問題なし

##### 5. データが登録されているか確認
```
select * from {TABLE名};
```
※ selectでできないときは大文字のSELECTで実行してみる(気分なのか小文字の時と大文字の時がある)
4.で登録したデータが表示されれば完了

##### 6. VPSのpostgreSQLにちゃんと同期されているか確認
###### 1. VPSのpostgreSQLに接続
```
psql -U {ユーザー名} -d {DB名}
```

###### 2. データが挿入されているかの確認
```
SELECT * from {TABLE名};
```
※ ※ SELECTでできないときは小文字のselectで実行してみる(気分なのか小文字の時と大文字の時がある)
先ほど挿入したデータが確認できれば完了

#### 2. Springbootの設定
##### 1. application.propertiesの変更
```
spring.jpa.database=POSTGRESQL
spring.datasource.url=jdbc:postgresql://{VPSのIPアドレス}:5432/{DB名}
spring.datasource.username={ユーザー名}
spring.datasource.password={パスワード}
```

##### 2. 依存関係の追加
pom.xml
```
<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>3.0.0</version>
</dependency>
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>
```
※ 今回はMybatisを使用していますがJPAでも可

##### 3. Modelクラスの作成
Model: データベースのデータをJavaのクラスとして扱うために必要
```
@Getter
@Setter
public class Test {
    private Long id;
    private String name;
}
```

##### 4. repositoryの作成
repository: 実際にデータベースとのやり取りをするためのインターフェース
```
@Mapper
public interface TestMapper {
    @Select("SELECT * FROM testTable")
    List<Test> selectAll();
}
```

##### 5. serviceクラスの作成
service: controllerとrepositoryの橋渡し役のような役割
```
@RequiredArgsConstructor
@Transactional
@Service
public class TestService {
    private final TestMapper mapper;
    public List<Test> selectAll() {
        return mapper.selectAll();
    }
}
```

##### 6. contorollerクラスの作成
contoroller: ここではユーザーからリクエストを受け取り、リクエストの内容に従ってサービスクラスを呼び出す処理
```
@RequiredArgsConstructor
@Controller
public class TestController {
    private final TestService service;
    @GetMapping("/list")
    public ModelAndView testList(ModelAndView mav) {
        mav.addObject("page", service.selectAll());
        mav.setViewName("list");
        return mav;
    }
}
```

##### 7. htmlの作成
```
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>list</title>
</head>
<body>
    <table>
        <tr th:each="list : ${page}" th:object="${list}">
            <td th:text="*{id}"></td>
            <td th:text="*{name}"></td>
        </tr>
    </table>
</body>
</html>
```
※ 一応備忘録として
`${page}`にはControllerのmav.addObjectで指定したservice.selectAll()(データの全件取得)が入っている。
`th:each`でlistの中にpageの内容が1つずつ入っていく(javaでいう`for(String list : page)`)
`th:object`はフォームにバインドするオブジェクト`${list}`に指定している。
→`th:object`を使用しない場合は以下のようになる。
```
        <tr th:each="list : ${page}">
            <td th:text="*{list.id}"></td>
            <td th:text="*{list.name}"></td>
        </tr>
```

##### 8. localで動作確認

#### 3. TABLEの削除
TABLEが必要なければpostgreSQLに接続した後、以下のコマンドで削除
```
drop table "{TABLE名}";
```


### エラー解消
- ERROR:  type "varcher" does not exist
VARCHARは大文字にしないといけない

- `drop table {TABLE名};`とやると`ERROR:  syntax error at or near "DROP"`が出て削除できない
`drop table "{TABLE名}";`とTABLE名をダブルクォーテーションで囲んであげる。

- VPSでpostgreSQLに接続したときに`psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432"`のエラー
sudo vi /var/lib/pgsql/14/data/pg_hba.confを以下のように修正
```
修正前
# "local" is for Unix domain socket connections only
local   all             all                                     peer

修正後
# "local" is for Unix domain socket connections only
local   all             all                                     trust
```

- localで動作確認したらinternal server errorが出る
おそらくapplicaion.propertiesに記載している内容がどこか間違っている
(自分はpw間違っていてエラー出た)

### 参考
- https://uha-blog.com/java/spring-boot-postgresql/
- https://www.koikikukan.com/archives/2020/06/03-235555.php