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

Cassandra驱动CodecNotFoundException:date与java.sql.Date映射异常排查

解决Datastax Driver 3.x中date <-> java.sql.Date的编解码错误

嘿,这个问题我之前在项目里也碰到过,咱们来一步步拆解原因和解决办法:

错误根源

你用的Datastax Java Driver 3.x版本,对Cassandra的date类型,默认只支持和Java 8新时间API里的java.time.LocalDate做映射,而你代码里用的是旧的java.sql.Date,驱动找不到对应的编解码器(Codec),所以抛出了CodecNotFoundException。

两种解决方案

方案1:改用java.time.LocalDate(推荐)

这是最规范的做法,因为Java 8的java.time包是官方推荐的时间处理方案,驱动原生支持,不需要额外配置:

  1. 修改你的IndustryCompany实体类,把create_date字段的类型从java.sql.Date改成java.time.LocalDate
  2. 重构today()方法,直接用Java 8的API生成LocalDate,不用再绕弯子转java.sql.Date:
import java.time.LocalDate;

public static LocalDate today() {
    return LocalDate.now();
}
  1. 保存数据的时候直接传递LocalDate对象,驱动会自动完成和Cassandradate类型的编解码

方案2:自定义编解码器(兼容现有代码)

如果因为项目历史原因不能修改现有代码的java.sql.Date类型,可以自定义一个Codec让驱动支持两者的转换:

  1. 编写自定义Codec类:
import com.datastax.driver.core.TypeCodec;
import com.datastax.driver.core.ProtocolVersion;
import com.datastax.driver.core.exceptions.InvalidTypeException;
import java.nio.ByteBuffer;
import java.sql.Date;
import java.time.LocalDate;

public class SqlDateToCassandraDateCodec extends TypeCodec<Date> {

    private final TypeCodec<LocalDate> localDateCodec = TypeCodec.date();

    public SqlDateToCassandraDateCodec() {
        super(com.datastax.driver.core.DataType.date(), Date.class);
    }

    @Override
    public ByteBuffer serialize(Date value, ProtocolVersion protocolVersion) throws InvalidTypeException {
        return (value == null) ? null : localDateCodec.serialize(value.toLocalDate(), protocolVersion);
    }

    @Override
    public Date deserialize(ByteBuffer bytes, ProtocolVersion protocolVersion) throws InvalidTypeException {
        return (bytes == null) ? null : Date.valueOf(localDateCodec.deserialize(bytes, protocolVersion));
    }

    @Override
    public Date parse(String value) throws InvalidTypeException {
        if (value == null || value.isEmpty() || value.equalsIgnoreCase("NULL")) return null;
        return Date.valueOf(localDateCodec.parse(value));
    }

    @Override
    public String format(Date value) throws InvalidTypeException {
        return (value == null) ? "NULL" : localDateCodec.format(value.toLocalDate());
    }
}
  1. 在初始化Cassandra Session的时候注册这个Codec:
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.CodecRegistry;

Cluster cluster = Cluster.builder()
        .addContactPoints("你的Cassandra节点地址")
        .withCodecRegistry(new CodecRegistry().register(new SqlDateToCassandraDateCodec()))
        .build();
Session session = cluster.connect();

额外提醒

你的today()方法原来的写法有点绕:先用SimpleDateFormat格式化当前时间,再转成java.sql.Date,这种方式不仅容易出线程安全问题(SimpleDateFormat是非线程安全的),还完全没必要,改用Java 8的LocalDate.now()既简洁又安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:18:41