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

Spring Boot+Hibernate自定义AttributeConverter插入报错求助

问题: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 cause

org.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数据。

按以下步骤修正:

  1. 正确实现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;
        }
    }
    
  2. 修正实体类与数据库列名匹配问题
    错误信息中数据库列是card_expiry_date,但实体类@Column指定的是expiry_date,需统一两者名称,避免映射错误。

  3. 检查仓库操作逻辑
    确保SingleUserDao中expiryDate的赋值逻辑正确,避免传入无法被转换器处理的错误数据类型。

  4. 确认数据库列类型
    验证数据库中目标列的类型确实为date,而非其他类型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 12:18:14