SpringBoot から Supabase DB接続 の簡易メモ

DB を無料で使えるサービス [Supabase](https://supabase.com/) を使って SpringBoot から接続したときの簡易メモ
Supabase は認証とかもあって使い道がいろいろとありそう
一旦は PostgreSQL を無料で使えるくらいでやってます

# 大雑把な流れ
- Supabase にプロジェクト作成・テーブル作成
- SpringBoot のプロジェクト作成・DB接続情報定義・モジュール作成

# 実行環境
- Windows11
- Pleiades 2024 Full Edition
- Maven v3.9.6
- SpringFramework Boot v3.4.4
- Java v21
- spring-boot-starter-data-jdbc
- spring-boot-starter-data-jpa
- PostgreSQL Driver

# Supabase にプロジェクト作成・テーブル作成
基本は流れに身を任せて進めれば作れると思います
参考程度にイメージはって手順のせてます
後続のデータ取得でつくる Entity, Repository はここで作ってるテーブルの設定でつくります

### Supabasee プロジェクト作成
1. Supabasee のサイトにアクセス
    https://supabase.com/
1. Start your project でアカウント作成に進む
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/59aceed2-18ee-4cf3-971a-747c4d1bb1fa.png)
1. アカウントをつくる（イメージは Github でつくるとき）
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/2a6e700a-6560-43f4-b1d1-db431e979c4f.png)
1. 各種の設定は初期設定でOK (料金 free じゃなかったら free にした方が安全)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/4b042c0e-b60a-413e-802c-b9dd9126dc11.png)
1. プロジェクト作成（とりあえず blank）
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/c05acfee-db75-4594-a252-67ad9afba8d3.png)
1. プロジェクト名、リージョン（日本にする）、パスワード入力(覚えておく)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/0fae987a-4cff-4820-948d-d08e62852fe9.png)

### Supabasee テーブル作成
1. Table Editor 選んで Create a new table を押す
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/9d1bebf6-4fc3-460b-accb-e6d6d1a91c92.png)
1. 以下の設定でテーブル作成
    - Name : wktable
    - Enable Row Level Security(RLS) ：チェックあり
    - Columns
        - id : 最初のまんま
        - created_at : 最初のまんま
        - message：Typeをtext
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/758efac1-1019-480c-8d97-a4a2b3596390.png)
1. テーブルのRLSポリシーを追加 (Add RLS policy)
    ここでは全部、許可の設定（要件に合わせてやった方が良いです）
    - Policy Name : なんでもOK
    - Policy Behavior : Permissive
    - Policy Command : とりあえず ALL
    - Target Roles : とりあえず public
    - using, with check : true
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/70b532a8-2415-47f8-be14-7054eb33c742.png)



# SpringBoot のプロジェクト作成・DB接続定義・モジュール作成
最低限の設定だけつけてDBの情報をコンソールログにとりあえずだすまでやってみる

### SpringBoot プロジェクト作成
1. SpringBoot の新規プロジェクトを作成する
    以下のところが気にするところ、それ以外はデフォルトでOK
    - タイプ：Maven
    - Javaバージョン：21
    - 依存関係：Spring Data JDBC, Spring Data JPA, PostgreSQL Driver をチェック（他はデフォルトのチェック残す）

### SpringBoot DB接続定義
1. application.properties に以下を追加
    - url : これは supabase より取得する URI (取得方法ちょっとしたを参照)
    - pool : とりあえず最小の設定（デフォルトだと何回か再起動でエラーになる）
    ```properties:application.properties
    spring.datasource.driver-class-name=org.postgresql.Driver
    spring.datasource.url=jdbc:postgresql://xxxxxxx.suapbase.com:6543/postgres?user=xxxxxxx&password=[YOUR-PASSWORD]
    spring.datasource.hikari.maximum-pool-size=1
    spring.datasource.hikari.minimum-idle=1
    spring.datasource.hikari.connection-timeout=30000
    spring.datasource.hikari.idle-timeout=300000
    spring.datasource.hikari.max-lifetime=1800000
    spring.datasource.hikari.leak-detection-threshold=5000
    spring.datasource.hikari.pool-name=SupabaseHikariPool
    spring.datasource.hikari.connection-test-query=SELECT 1

    spring.jpa.hibernate.ddl-auto=none
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect    
    ```

    - supabase で URI を取得（ Connect → Type を JDBC → Transaction pooler）
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/7694005a-c013-428a-a9ac-988f02e9fb50.png)    
    
### SpringBoot モジュール作成
1. Entity 
    ```Java:Wktable.java
    package com.example.demo;

    import java.util.Date;

    import org.hibernate.annotations.CreationTimestamp;

    import jakarta.persistence.Entity;
    import jakarta.persistence.GeneratedValue;
    import jakarta.persistence.GenerationType;
    import jakarta.persistence.Id;
    import lombok.Data;

    @Data
    @Entity
    public class Wktable {

    	@Id
    	@GeneratedValue(strategy = GenerationType.IDENTITY)
    	private Long id;
    	@CreationTimestamp
    	private Date createdAt;
    	private String message;
    
    }
    ```
1. Repository
    ```Java:WktableRepository.java
    package com.example.demo;

    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;

    @Repository
    public interface ChatRepository extends JpaRepository<Chat, Long> {
    }
    ```
1. Controller
    ```Java:GetDbController.java
    package com.example.demo;

    import java.util.List;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class GetDbController {

    	@Autowired
    	WktableRepository wktableRepository;

    	@GetMapping("/getdb")
    	public List<Wktable> getdb() {
    		List<Wktable> wktables = wktableRepository.findAll();
    		wktables.forEach(wktable -> {
    			System.out.println(wktable.getId());
    			System.out.println(wktable.getCreatedAt());
    			System.out.println(wktable.getMessage());
    		});
    		return wktables;
    	}
    }
    ```