Hibernate读取实体枚举字段抛NumberFormatException异常问题排查
JPA实体类枚举字段数据转换异常排查
问题描述
访问声明为自定义枚举类型的实体类字段时抛出数据转换异常,错误栈提示字符串转整数失败。
相关代码片段
枚举定义
public enum OrderMetaDataAttribute { PARTY_ID("partyId"), PARTY_NAME("partyName"), [...] }
实体类定义
@Table public class OrderMetaData extends AbstractPersistentObject { @Column(nullable = false) private OrderMetaDataAttribute attribute; [...] }
测试插入SQL
insert into order_meta_data (id, attribute, value, order_id) values ('11', 'PARTY_ID', '0815', '1'), ('12', 'PARTY_NAME', 'testParty', '1');
异常信息
org.hibernate.exception.DataException: Could not read entity state from ResultSet : EntityKey[org.exmaple.order.model.OrderMetaData#11] [...] Caused by: org.h2.jdbc.JdbcSQLDataException: Datenumwandlungsfehler beim Umwandeln von "partyId" Data conversion error converting "partyId" [22018-200] at org.h2.message.DbException.getJdbcSQLException(DbException.java:457) [...] Caused by: java.lang.NumberFormatException: For input string: "partyId" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) at org.h2.value.Value.convertToInt(Value.java:982) at org.h2.value.Value.convertTo(Value.java:806) ... 107 more
根因分析
JPA默认对枚举类型字段采用EnumType.ORDINAL映射策略,会将枚举值对应为从0开始的整数存储、读取,因此Hibernate会尝试将数据库中读取到的attribute字段值转为整数,和枚举的序号匹配。但当前数据库中该字段存储的是字符串类型值,转换时触发NumberFormatException。
额外说明:如果业务需要存储枚举自定义的属性值(比如本示例中PARTY_ID对应的partyId),仅使用@Enumerated注解无法实现,需要额外自定义属性转换器。
解决方案
根据业务存储需求选择对应方案即可:
- 场景1:需要存储枚举的字面量名称(比如
PARTY_ID、PARTY_NAME)
给实体类的枚举字段加上@Enumerated(EnumType.STRING)注解:@Column(nullable = false) @Enumerated(EnumType.STRING) private OrderMetaDataAttribute attribute; - 场景2:需要存储枚举自定义的属性值(比如本示例中的
partyId、partyName)
自定义AttributeConverter实现转换逻辑,示例如下:@Converter(autoApply = true) public class OrderMetaDataAttributeConverter implements AttributeConverter<OrderMetaDataAttribute, String> { @Override public String convertToDatabaseColumn(OrderMetaDataAttribute attribute) { return attribute == null ? null : attribute.getValue(); } @Override public OrderMetaDataAttribute convertToEntityAttribute(String dbValue) { if (dbValue == null) { return null; } for (OrderMetaDataAttribute attr : OrderMetaDataAttribute.values()) { if (attr.getValue().equals(dbValue)) { return attr; } } throw new IllegalArgumentException("未知的枚举值: " + dbValue); } }
内容的提问来源于stack exchange,提问作者Jonas_Hess
相关产品推荐
相关产品推荐

