Не отрабатывает enum converter в spring-data

Рейтинг: 0Ответов: 1Опубликовано: 26.04.2023

Такая проблема, у меня в коде не отрабатывает конвертер для перечислений, причем делаю его не у первый раз, но на новом проекте не хочет отрабатывать. Перечисления такие:

Раз:

    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. Либо менять структуру сущности, либо смириться и сделать некрасивое перечисление.