首页 > 解决方案 > 如何将带有hypen的mysql枚举类型映射到JPA实体?

问题描述

mysqlsakila.film中有一个表,其字段rating类型为enum('G','PG','PG-13','R','NC-17')

我正在尝试使用类型将其映射到 JPA 实体中enum@Enumerated(EnumType.STRING)但不能这样做,因为 java 枚举不允许连字符。也无法更改或更新表,因为它有大量数据并给出错误 - “数据被截断为列 'rating'”

如何进行?

标签: javamysqlhibernatejpa

解决方案


这类事情是JPA 属性转换器旨在帮助实现的目标。

首先,您需要将 Javaenum元素映射到数据库中找到的字符串,并提供一种查找方法来将字符串转换为元素:

public enum Rating {
    G("G"), // the string arguments should exactly match what's in the database.
    PG("PG"),
    PG13("PG-13"),
    R("R"),
    NC17("NC-17");

    private static final Map<String, Rating> LOOKUP = Arrays.stream(values())
            .collect(Collectors.toMap(Rating::getRating, Function.identity()));

    private final String rating;

    Rating(final String rating) {
        this.rating = rating;
    }

    public String getRating() {
        return rating;
    }

    public Rating fromString(final String rating) {
        // You may want to include handling for the case where the given string
        // doesn't map to anything - implementation is up to you.
        return LOOKUP.get(rating);
    }
}

接下来,您将需要一个实现的类javax.persistence.AttributeConverter

public static class RatingConverter implements AttributeConverter<Rating, String> {
    @Override
    public String convertToDatabaseColumn(final Rating attribute) {
        return attribute.getRating();
    }

    @Override
    public Rating convertToEntityAttribute(final String dbData) {
        return Rating.fromString(dbData);
    }
}

从这里您需要决定是否应始终应用此转换器(听起来可能应该)。

如果您希望它始终在您没有进一步配置的情况下使用,请使用@javax.persistence.Converter(autoApply = true).

如果要选择何时使用转换器,则需要将注释添加@javax.persistence.Convert(converter = RatingConverter.class)到需要它的每个 JPA 实体的 Rating 属性中。

就我个人而言,我通常将转换器作为静态类嵌套在它们转换的类中,但如果您希望将它们分开,则不必这样做。


推荐阅读