You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在JPA中使用带自定义属性的枚举作为ID时遇数据转换异常

问题:自定义枚举作为JPA实体ID时查询抛出类型转换异常

实体与Repository定义

我定义了如下JPA实体,使用自定义枚举作为ID字段:

public class Entity {

    @Id
    @Column(name = "id")
    private EntityId id;

    @RequiredArgsConstructor
    public enum EntityId {

        A("a"),
        B("b"),
        C("c"),
        D("d");

        @Getter
        private final String id;

    }

}

对应的Repository接口:

public interface EntityRepository extends JpaRepository<Entity, Entity.EntityId> {
}

异常信息

调用EntityRepository#findAll时抛出异常,核心栈信息如下:

org.springframework.dao.DataIntegrityViolationException: could not execute query; SQL [select entity0_.id as id_1_2_ from entity entity0_];

...

Caused by: org.hibernate.exception.DataException: could not execute query

...

Caused by: org.h2.jdbc.JdbcSQLDataException: Data conversion error converting "b" [22018-200]

...

Caused by: java.lang.NumberFormatException: For input string: "b"

背景说明

  • 已创建对应AttributeConverter<Entity.EntityId, String>,但问题未解决
  • 若移除枚举中的id属性并使用@Enumerated(STRING)可正常运行,但业务要求必须保留该属性
  • 数据库表ID为字符串类型,存储值为"a"、"b"、"c"、"d",无法使用枚举的ordinal或name映射(枚举名是"A"、"B"等,与存储值不匹配)

解决方案

1. 正确实现并注册AttributeConverter

确保转换器类添加@Converter注解,实现正确的双向转换逻辑:

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.util.Arrays;

@Converter(autoApply = true) // 自动应用到所有Entity.EntityId类型的属性
public class EntityIdConverter implements AttributeConverter<Entity.EntityId, String> {

    @Override
    public String convertToDatabaseColumn(Entity.EntityId entityId) {
        return entityId != null ? entityId.getId() : null;
    }

    @Override
    public Entity.EntityId convertToEntityAttribute(String dbValue) {
        return dbValue != null ? Arrays.stream(Entity.EntityId.values())
                .filter(id -> id.getId().equals(dbValue))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("无效的ID值: " + dbValue)) : null;
    }
}

2. 让枚举实现Serializable接口

JPA要求ID类型必须可序列化,因此需要给枚举添加Serializable实现:

@RequiredArgsConstructor
public enum EntityId implements Serializable { // 添加Serializable接口
    A("a"),
    B("b"),
    C("c"),
    D("d");

    @Getter
    private final String id;
}

3. (可选)手动指定转换器

如果autoApply = true未生效,可在实体的ID字段上手动关联转换器:

@Id
@Column(name = "id")
@Convert(converter = EntityIdConverter.class) // 手动指定转换器
private EntityId id;

内容的提问来源于stack exchange,提问作者thmasker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:25:19