Spring Boot+Hibernate自定义AttributeConverter插入报错求助
我想在Spring Boot+Hibernate应用中实现自定义列处理器,尝试了以下代码:
实体类代码
@Entity @Table(name = "single_user") @Getter @Setter public class SingleUser { @Id @SequenceGenerator(name = "su_seq", sequenceName = "su_seq", allocationSize = 100) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "su_seq") @Column(name = "id", nullable = false) private Long id; @Convert(converter = ExpiryDateTypeHandler.class) @Column(name = "expiry_date") private ExpiryDate expiryDate; // getter, setter }
Spring JPA仓库代码片段
SingleUserDao entity; singleUserRepository.create(entity.getId(), ....., Optional.ofNullable(entity.getRecipient()).map(CalendarDate::getYear).orElse(0),
插入时的错误信息
[ERROR: column "card_expiry_date" is of type date but expression is of type bytea
Hint: You will need to rewrite or cast the expression.
Position: 215] [n/a]; SQL [n/a]] with root causeorg.postgresql.util.PSQLException: ERROR: column "card_expiry_date" is of type date but expression is of type bytea
Hint: You will need to rewrite or cast the expression.
请问如何正确实现AttributeConverter以完成数据插入?
错误核心是ExpiryDateTypeHandler未正确实现AttributeConverter接口的双向转换逻辑,导致Hibernate无法将ExpiryDate映射为数据库date类型,默认进行序列化生成bytea数据。
按以下步骤修正:
正确实现
AttributeConverter接口
数据库date类型对应Java的LocalDate(推荐Java 8+时间API),转换器需在ExpiryDate与LocalDate间双向转换:import jakarta.persistence.AttributeConverter; import jakarta.persistence.Converter; import java.time.LocalDate; @Converter(autoApply = true) // 可选:自动应用到所有ExpiryDate类型属性 public class ExpiryDateTypeHandler implements AttributeConverter<ExpiryDate, LocalDate> { // 自定义类型转数据库存储类型 @Override public LocalDate convertToDatabaseColumn(ExpiryDate expiryDate) { if (expiryDate == null) { return null; } // 假设ExpiryDate包含year、month字段,构建LocalDate(日期可设为当月1日) return LocalDate.of(expiryDate.getYear(), expiryDate.getMonth(), 1); } // 数据库类型转自定义实体类型 @Override public ExpiryDate convertToEntityAttribute(LocalDate dbDate) { if (dbDate == null) { return null; } ExpiryDate expiryDate = new ExpiryDate(); expiryDate.setYear(dbDate.getYear()); expiryDate.setMonth(dbDate.getMonthValue()); return expiryDate; } }修正实体类与数据库列名匹配问题
错误信息中数据库列是card_expiry_date,但实体类@Column指定的是expiry_date,需统一两者名称,避免映射错误。检查仓库操作逻辑
确保SingleUserDao中expiryDate的赋值逻辑正确,避免传入无法被转换器处理的错误数据类型。确认数据库列类型
验证数据库中目标列的类型确实为date,而非其他类型。
内容的提问来源于stack exchange,提问作者Peter Penzov

