Spring Data JPA において、@Enumerated に指定した列が想定外の値でマップされる

More than 1 year has passed since last update.


概要

Spring Data JPA において、@Enumerated を指定したフィールドを定義した結果、指定した Enum の型にて値がマップされますが、マップされる値が想定外の値になる現象が発生しました。

下記の例だと、JpaRepository にて find を実施すると、CompanyDetail#companyType は、FOOD となる動作となりました。

どうやら、Enum の先頭のフィールド名にてデータが取得される動作になっているようでした。


Company.java

@Getter

@Entity
public class Company implements Serializable {

@Id
private int id;

@Embedded
private CompanyDetail companyDetail;
}



CompanyDetail.java

@Embeddable

@Getter
@NoArgsConstructor
public class CompanyDetail implements Serializable {
@Enumerated(EnumType.STRING)
private CompanyType companyType;
private String zipCode;
private String email;
}


CompanyType.java

@Getter

public enum CompanyType {
FOOD(1),
MANUFACTURER(2),
OTHER(0);
private int businessConditions;

CompanyType(int businessConditions) {
this.businessConditions = businessConditions;
}
}



回避策

CompanyDetail クラスに @Column(nullable = false) を設定することで正常の値にてマップされるようになりました。

@Enumerated を指定した際は、null を許容しないことを明示する必要がありそうです。


CompanyDetail.java

@Embeddable

@Getter
@NoArgsConstructor
public class CompanyDetail implements Serializable {
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private CompanyType companyType;
private String zipCode;
private String email;
}


補足

@Enumerated は Enum の値を DB に格納することを宣言するアノテーションです。上記例では、EnumType.STRING を指定することで Enum.name() を DB に格納するよう指定しております。

Enum.ordinal() にて格納した際、 格納された値からなんの区分であるかについて推測することが困難になり、また、Enum の定義順 (FOOD, MANUFACTURER, OTHER) で数字が割り当てられるため、非常に恣意的な値が格納されます。(Enum 値が追加されると順番がずれます)

そのため、文字列にて値を格納するよう設計しております。

下記資料に上記動作の説明がないため、動作の根本原因については不明ですが、@Embedded にて値オブジェクトを埋め込んでいるか、あるいは STRING にて値をマップしているために発生している可能性があるかもしれません。

タイトル : Java Persistence/Basic Attributes

アドレス: https://en.wikibooks.org/wiki/Java_Persistence/Basic_Attributes#Enums


Java Enums are typically used as constants in an object model. For example an Employee may have a gender of enum type Gender (MALE, FEMALE).

By default in JPA an attribute of type Enum will be stored as a Basic to the database, using the integer Enum values as codes (i.e. 0, 1). JPA also defines an @Enumerated annotation and element (on a ) to define an Enum attribute. This can be used to store the Enum as the STRING value of its name (i.e. "MALE", "FEMALE").