R2DBC执行save时报错Cannot encode java.util.Date参数如何解决
结论
R2DBC完全支持日期类型存储,你遇到的报错是类型映射不匹配、字段对应错误、驱动使用偏差三个问题共同导致的,可按以下方案解决:
问题根因
- 驱动匹配错误:报错栈显示调用的是
io.r2dbc.h2.codecs.DefaultCodecs,说明当前运行环境实际连接的是H2数据库而非你预期的MySQL,H2的R2DBC驱动默认未提供java.util.Date类型的编码器。 - 字段映射错误:实体类
verificationTokenType字段对应数据库列名是verification_token_type_id,未显式指定映射会导致参数绑定错位。 - 旧日期API适配不足:
java.util.Date是JDK1.0时代的旧日期API,R2DBC默认优先适配JSR310规范的新日期类型(LocalDateTime、Instant等),旧类型需要额外配置转换器。
解决步骤
方案一:替换为新日期API(推荐,无需额外配置)
直接将实体类中的java.util.Date类型替换为LocalDateTime,Spring Data R2DBC默认自带该类型和数据库datetime类型的映射转换器:
@Table public class VerificationToken { @Id private final Long id; @Column private final String code; // 替换为LocalDateTime类型 @Column private final LocalDateTime validUntil; @Column private boolean used; @Column("user_id") private Long userId; // 显式指定对应数据库列名 @Column("verification_token_type_id") private Long verificationTokenType; }
方案二:业务必须使用java.util.Date时自定义转换器
如果不能修改原有日期类型,可自定义读写转换器注册到R2DBC配置中:
- 编写转换器实现:
import org.springframework.core.convert.converter.Converter; import org.springframework.data.r2dbc.convert.ReadingConverter; import org.springframework.data.r2dbc.convert.WritingConverter; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Date; // 写入数据库时:Date转LocalDateTime @WritingConverter public class DateToLocalDateTimeConverter implements Converter<Date, LocalDateTime> { @Override public LocalDateTime convert(Date source) { return source.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); } } // 读取数据时:LocalDateTime转Date @ReadingConverter public class LocalDateTimeToDateConverter implements Converter<LocalDateTime, Date> { @Override public Date convert(LocalDateTime source) { return Date.from(source.atZone(ZoneId.systemDefault()).toInstant()); } }
- 注册转换器到R2DBC配置:
import org.springframework.context.annotation.Configuration; import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration; import java.util.List; @Configuration public class R2dbcCustomConfig extends AbstractR2dbcConfiguration { @Override protected List<Object> getCustomConverters() { return List.of(new DateToLocalDateTimeConverter(), new LocalDateTimeToDateConverter()); } }
- 同样要修正实体类的字段映射注解,和方案一的字段注解保持一致。
额外校验
检查项目配置文件中的R2DBC连接地址,确认是MySQL连接地址而非H2地址,避免驱动不匹配问题:
# 示例MySQL R2DBC配置 spring: r2dbc: url: r2dbc:mysql://localhost:3306/你的库名 username: 账号 password: 密码
内容的提问来源于stack exchange,提问作者AleGallagher
相关产品推荐
相关产品推荐

