LocalDateを使おうとすると、date型じゃだめ、timestampを使いなさいと言われた(spring boot)
『Spring徹底入門』の「第14章チュートリアル」を写経していて、エラーが出たので
そのメモ。
p642…p652 まで入力して、本に書かれてあるように Spring Boot の この
プロジェクトを再起動すると、以下のようなエラーが出た。
Schema-validation: wrong column type encountered in column [reserved_date] in table [reservable_room]; found [date (Types#DATE)], but expecting [timestamp (Types#TIMESTAMP)]
意味としては、
「テーブル[reservable_room] の中のカラム [reserved_date] のデータ型が悪い。
[timestamp] を期待していたのに、[date] だったよ。」
というような感じかな。
p652 の SQL文は、PostgreSQLのコマンドで実行しても、すんなり通ったので、
問題があるとするなら、Javaのコード。
ReservableRoom.java
package mrs.domain.model;
import java.io.Serializable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapsId;
@Entity
public class ReservableRoom implements Serializable {
// 複合主キー であることを表現するために、型をクラスとしている。
// ReservableRoomId は roomId と reservedDate である。
@EmbeddedId
private ReservableRoomId reservableRoomId;
// 多対1、
// @JoinColumn -- 外部キーは、テーブルでは room_id になる。
// @MapId -- 複合主キー ReservableRoomId のうち、参照するのは roomId である。
@ManyToOne
@JoinColumn(name = "room_id", insertable = false, updatable = false)
@MapsId("roomId")
private MeetingRoom meetingRoom;
public ReservableRoom(ReservableRoomId reservableRoomId) {
this.reservableRoomId = reservableRoomId;
}
public ReservableRoom() {}
// getter, setter は省略
}
このコードの ER図 は、以下である。
+----------------------------+
| reservable_room |
+----------------------------+
| (key) reserved_date : date |
| (key) roomId : int |
+----------------------------+
複合主キーになっているので、Javaコードでは、ReservedRoomIdクラスとして
表現している。
ReservedRoomIdクラスは以下である。
ReservableRoomId.java
package mrs.domain.model;
import java.io.Serializable;
import java.time.LocalDate;
import javax.persistence.Column;
import javax.persistence.Embeddable;
@Embeddable
public class ReservableRoomId implements Serializable {
private Integer roomId;
private LocalDate reservedDate; // <== ここ
public ReservableRoomId(Integer roomId, LocalDate reservedDate) {
this.roomId = roomId;
this.reservedDate = reservedDate;
}
public ReservableRoomId() {}
@Override
public int hashCode() {
( 省略 )
}
@Override
public boolean equals(Object obj) {
( 省略 )
}
// getter, setter は省略
}
結論からいうと、上の
private LocalDate reservedDate;
を
@Column(columnDefinition = "DATE")
private LocalDate reservedDate;
とすると、エラーは消えた。
追記・原因がわかった
原因がわかった。p.650からの LocalDateConverter.java、LocalTimeConverter.java、LocalDateTimeConverter.java を書いたからだった ^^;
JPA2.1では LocalDate などに対応していないので、このコンバーターが必要なのだが、
今の僕の環境では必要ない。
つまり、LocalDate をわざわざ Timestamp に変換して読み込もうとしていたのである。
それを抑止する役目をしていたのが、columnDefinition = “DATE” だったというわけである。
参考
環境
- Ubuntu 22.04.2 LTS
- Java 1.8
- spring-boot 2.7.9
- Eclipse 2022-03
カテゴリー: Java, memo
タグ: JPA, LocalDate, spring, spring-boot, timestamp
カウント: 204