Не отрабатывает enum converter в spring-data
Такая проблема, у меня в коде не отрабатывает конвертер для перечислений, причем делаю его не у первый раз, но на новом проекте не хочет отрабатывать. Перечисления такие:
Раз:
public enum ImageSize {
HIGH("h", 1200),
LOW("l", 450),
PREVIEW("p", 160),
NONE("n", null);
@Getter
final String dbValue;
@Getter
final Integer sideLength;
ImageSize(String dbValue, Integer sideLength) {
this.dbValue = dbValue;
this.sideLength = sideLength;
}
Два:
public enum ImageType {
OBSERSE("o"),
REVERSE("r"),
PACKAGING("p"),
SPRITE("s");
@Getter
private final String dbValue;
ImageType(String dbValue) {
this.dbValue = dbValue;
}
}
Далее, сущность вот такая:
@Table(name = "image")
@Entity
@Getter
@Setter
@ToString(exclude = "content")
@NoArgsConstructor
@AllArgsConstructor
@IdClass(Image.PK.class)
public class Image implements Persistable<Image.PK>, Persistence {
@Id
@JoinColumn(name = "catalog_num_code")
private String catalogNumCode;
@Id
@Column(name = "type", nullable = false, length = 1)
@Convert(converter = ImageTypeConverter.class)
private ImageType type;
@Id
@Column(name = "size", nullable = false, length = 1)
@Convert(converter = ImageSizeConverter.class)
private ImageSize size;
@Lob
@Type(type = "org.hibernate.type.BinaryType")
@Column(name = "content", columnDefinition="bytea")
private byte[] content;
@UpdateTimestamp
@Column(name = "modify_At")
private Timestamp modifyDate;
@Override
public PK getId() {
return new Image.PK(catalogNumCode, type, size);
}
@Override
public boolean isNew() {
return false;
}
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@EqualsAndHashCode
public static class PK implements Serializable {
private String catalogNumCode;
private ImageType type;
private ImageSize size;
}
}
И, соответственно, вот такие конвертеры:
Раз:
@Converter
public class ImageTypeConverter implements AttributeConverter<ImageType, String> {
@Override
public String convertToDatabaseColumn(ImageType type) {
if (type == null) {
return null;
}
return type.getDbValue();
}
@Override
public ImageType convertToEntityAttribute(String value) {
if (value == null) {
return null;
}
return Stream.of(ImageType.values())
.filter(type -> type.getDbValue().equals(value))
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
Два:
@Converter
public class ImageSizeConverter implements AttributeConverter<ImageSize, String> {
@Override
public String convertToDatabaseColumn(ImageSize size) {
if (size == null) {
return null;
}
return size.getDbValue();
}
@Override
public ImageSize convertToEntityAttribute(String value) {
if (value == null) {
return null;
}
return Stream.of(ImageSize.values())
.filter(type -> type.getDbValue().equals(value))
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
Таблица создавалась вот так:
CREATE TABLE IF NOT EXISTS image
(
catalog_num_code varchar(10),
type varchar(1),
size varchar(1),
content bytea not null,
modify_at timestamp,
primary key (catalog_num_code, type, size)
);
При попытке сохранить новый объект Image получаю:
org.postgresql.util.PSQLException: ERROR: operator does not exist: character varying = integer Подсказка: No operator matches the given name and argument types. You might need to add explicit type casts. Позиция: 252
Как я понимаю, по умолчанию перечисление воспринимается как @Enumerated(value = EnumType.ORDINAL) и соответственно в БД летит целое число вместо строки. Конвертеры не отрабатывают вообще, ставлю дебаг на методы конвертера, программа там не идёт. Что я упустил??
Ответы (1 шт):
Собственно, надо было почитать джавадок конвертера. Цитирую:
Note that Id attributes, version attributes, relationship attributes, and attributes explicitly annotated as Enumerated or Temporal (or designated as such via XML) will not be converted.
Как раз мой случай, когда оба перечисления являются частью составного ключа и помечены аннотацией @Id. Либо менять структуру сущности, либо смириться и сделать некрасивое перечисление.