開発授業中にエラーで詰まったことリスト

# 更新
cascadeの意味教えてもらった
PERSISTとDETACH、これテストに出ます。
メリットとデメリットがある。トランザクションに関連しまくりなのでDETACHを推奨します

# 開発環境
+ spring-boot-2.7.0
+ thymeleaf-3.0.15.RELEASE
+ jackson-2.13.3
+ h2-2.1.212
+ log4j-slf4j-impl-2.17.2
+ jakarta-annotation-api-1.3.5
+ jakarta.validation-api-2.0.2
+ lombok-1.18.24

## アノテーション
@NotNullとか同じ名前、似たような名前がありますがそれぞれ動作が異なります。
コンパイル時に値を確認する条件分岐を追加するものもあれば、コーディング時にnullになる可能性がありますとか。
+ [nullじゃない三銃士](https://takeda-san.hatenablog.com/entry/2018/05/30/235154)

## 自動生成でSQL文生成を利用
**インターフェースクラスに@Repositoryを付与すること**

save()メソッドの仕様
※自動採番採用している場合だけど
主キーがnullの場合は自動採番をしてテーブルに挿入される
nullじゃない場合は更新される。

+ [Spring Data リポジトリの操作](https://spring.pleiades.io/spring-data/jpa/docs/current/reference/html/#repositories)
+ [リポジトリクエリキーワード](https://spring.pleiades.io/spring-data/jpa/docs/current/reference/html/#appendix.query.method.subject)

## テーブルをクラスで定義
JPAを利用してテーブルを作成してやろうと思い、テーブルをクラスで定義、起動。
テストデータが追加されるはずが、ログに「**テーブルが存在しない**」とエラーを吐かれた。
@Tableがjpaのアノテーションではなかったことが問題であった。
jpaアノテーションにしてもまた同じエラーが。
初期化後にsqlファイルを実行されるように設定をしていなかったことも原因だった。

~~~
spring.jpa.defer-datasource-initialization=true 
~~~

### @Columnつけるべきなのか？
付与しなくとも自動的に変数名を列名としてテーブルに定義してくれる。

### @OneToOne, @OneToMany @ManyToOne, @ManyToMany?
自動的に主キーに関連しているレコードをリスト型で格納するようになる。
いちいちDBに問い合わせしなくてもよくなる。
主キーの変数名を必ずidにしなくてはいけないらしい。
~~~diff_java
Studentクラス
@OneToOne
private StudentClass clazz;//mappedby="フィールド名"

StudentClassクラス
//クラスに所属している学生の一覧
@OneToMany(mappedby="clazz")//変数名だぞ！
private List<Student> studentList;
~~~

テーブル作成時のちょっとした自分へのアドバイス
必ず**誰**が**何時**作成したのかを記録するようにしろ

### 循環参照（相互参照）をしているテーブルは気を付けよう
Buffer Overflow!? What is this!
json形式でデータ保存しているらしく参照が悪さをしていた。
参照しているgetterを自分で定義して止めるしかない。
~~~diff_java
@Data
@Table
@Entity
public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
        
    private String name;
    
    private User createdBy; // <-原因

    //これで解決
    public int getCreatedBy(){
        return this.createdBy.id;    
    }
}
~~~
#### cascade
親から子へ操作を伝搬するという意味。
気をつけろ。特に循環参照または相互参照している場合は、適切な設定をしないとレコードすべて消えるしお前はクビになる可能性が出る。
ぷよぷよみたいに全消ししてもいいことは一つもない。

**脳死でALLはアカン**
+ PERSIST 
インスタンス内のデータを変更するとDBにも反映される
+ MERGE
レコードの内容が異なる場合は、更新をする。
+ REMOVE
レコードを削除する。
+ REFRESH
レコードに関連するテーブルを再読み込みします。
+ DETACH
PERSISTを解除する
インスタンス内のデータを変更してもDBに反映されない

## カスタム自動採番
自動採番を自作したいと思いUUIDGeneratorクラスのソースコードを見たりSeqenceStyleGeneratorクラスの使い方を調べたりした。
毎日、連番をリセットしなくてはいけないので定期実行のやり方を調べた。

+ [How to Implement a Custom, Sequence-Based ID Generator](https://thorben-janssen.com/custom-sequence-based-idgenerator/)
+ [Spring Bootでtaskを定期実行する方法](https://qiita.com/rubytomato@github/items/4f0c64eb9a24eaceaa6e) 
~~~diff_java
@Id
@GeneratedValue(generator = "aaid_seq")
@GenericGenerator(name = "aaid_seq", strategy = "AAIDGenerator", parameters = @Parameter(name = AAIDGenerator.INITIAL_PARAM, value = "21"))
private String id;
~~~

~~~diff_java
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.LongType;
import org.hibernate.type.Type;
import org.springframework.scheduling.annotation.Scheduled;

public class AAIDGenerator extends SequenceStyleGenerator {

	private Properties params;
	private ServiceRegistry serviceRegistry;

	@Override
	public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
		Serializable seq_gen = super.generate(session, object);
		String date = new SimpleDateFormat("yyyyMMdd").format(new Date(System.currentTimeMillis()));
		String value = String.format("P%s%05d", date, seq_gen);
		return value;
	}

	@Override
	public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
		this.params = params;
		this.serviceRegistry = serviceRegistry;
		super.configure(LongType.INSTANCE, params, serviceRegistry);
	}

	@Scheduled(cron = "0 0 0 * * *", zone = "Asia/Tokyo")
	public void resetSeqence() {
		super.configure(LongType.INSTANCE, this.params, this.serviceRegistry);
	}
}
~~~

## 値をアノテーションでチェック
時間が足りずに実装できなかった。
+ [【SpringBoot2】自作アノテーションの作成と入力チェックについて](https://qiita.com/shun-g/items/16ebd149afec831e521c)

## すべてのページで実行したい
+ [【Spring Boot】Controller Advice](https://b1san-blog.com/post/spring/spring-advice/)
接続した回数を記録する簡単なクラス
~~~diff_java
@ControllerAdvice
public class CommonAttribute {

	@ModelAttribute
	public void addAttributes(@ModelAttribute String count,Principal principal, Model model) {
		model.addAttribute("count", count++);
	}
}
~~~

~~~diff_html
<div th:text=${count}></div>
~~~

## 各クラスの責務を明確化しろ
クラスの内容が規則性のあるものになるため可読性が向上する。
メソッドのシグネチャになどが伝わりやすくなる。

### Controllerクラス
Serviceクラスから画面に設定するEntityを受け取るだけ
### Serviceクラス
Contorollerクラスから要求がデータベースなどに要求し結果をEntityに設定をして返すだけ
### Repositoryクラス（Crudクラス）
DBに問い合わせを行い結果を返すだけ
## ログ出力すべきもの
Controllerクラス
+ method(postとかgetとか)
+ マップ(url)
+ パラメータ(?以降の名前と値)
+ Attributeで設定したもの

Serviceクラス
+ メソッド名
+ 引数

Repositoryクラス（Crudクラス）
+ レポジトリークラスの名前
+ メソッド名
+ 引数
+ 問い合わせの結果

### ログに色を
デバッグやエラー様々なものをぱっと見で確認できた方がいいよねってことになり、色付けの仕方を調べました。
ANSI Escape in Consoleが最新のEclipseで入っていないことが分かったの。
マーケットプレイスからインストールをした、でも色がつかない。
先生に聞いても原因がわからなかったから、海外のフォーラムなど調べた。
log4j2の設定でdisableAnsiの値が初期値でtrueになっているため色がつかないとのこと。
falseに変更すれば解決するようだ。
~~~
<PatternLayout disableAnsi="false" pattern="${LOG_PATTERN}" />
~~~