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包是官方推荐的时间处理方案,驱动原生支持,不需要额外配置:
- 修改你的
IndustryCompany实体类,把create_date字段的类型从java.sql.Date改成java.time.LocalDate - 重构
today()方法,直接用Java 8的API生成LocalDate,不用再绕弯子转java.sql.Date:
import java.time.LocalDate; public static LocalDate today() { return LocalDate.now(); }
- 保存数据的时候直接传递
LocalDate对象,驱动会自动完成和Cassandradate类型的编解码
方案2:自定义编解码器(兼容现有代码)
如果因为项目历史原因不能修改现有代码的java.sql.Date类型,可以自定义一个Codec让驱动支持两者的转换:
- 编写自定义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()); } }
- 在初始化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
相关产品推荐
相关产品推荐

