java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timest

本文介绍了解决MySQL数据库中时间类型出现错误的情况,例如遇到'0000-00-0000:00:00'这类无法转换的时间格式时,通过配置URL参数zeroDateTimeBehavior=convertToNull来将无效的时间数据转换为NULL,从而避免程序抛出异常。

在查询数据库时间类型时,如若出现时间格式错误如:0000-00-00 00:00:00  则会抛出

java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timest 错误


问题是时间类型存储错误,解决方案:

    jdbc.url=jdbc:mysql:ip地址:端口号数据库名称?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull

解决方案即是url后面添加加参数:zeroDateTimeBehavior=convertToNull


此参数是指定时间类型错误处理策略为:错误则指定为null

策略:

    1.exception(不指定,则默认)---->默认抛出异常,
    2.convertToNull------->转化为null
    3.round------->替换成最近的日期即XXXX-01-01



参考文章:

        https://blog.youkuaiyun.com/rendeyishi/article/details/25119029

        https://blog.youkuaiyun.com/sinat_30397435/article/details/72518215

url常用参数设置参考:

        https://www.cnblogs.com/yokoboy/archive/2013/03/01/2939315.html


<think> 我们正在解决一个特定的异常:`org.springframework.dao.TransientDataAccessResourceException: Error attempting to get column 'update_time' from result set. Cause: java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp` 这个问题的根本原因是:数据库中的`update_time`字段的值为`'0000-00-00 00:00:00'`,而Java的`java.sql.Timestamp`无法表示这个值(因为它不符合Java中的日期时间范围,Java要求年份至少为1970)。 解决方案的核心思路:避免从数据库中得到这样的非法值,或者在得到这样的值时能够进行转换处理。 参考站内引用[^1]提到了类似的问题(虽然报错信息不完全相同,但都是关于从结果集获取列的问题),但并没有直接给出解决这个特定问题的办法。不过,我们可以根据经验提供以下几种解决方案: 1. **修改数据库中的非法日期值**:将数据库中所有`'0000-00-00 00:00:00'`的值修改为一个合法的默认值(例如`1970-01-01 00:00:00`或者`NULL`)。这是最彻底的解决方法,但需要确保业务逻辑允许。 2. **修改数据库表结构**:将`update_time`字段的默认值设置为一个合法的值(如`NULL`或一个具体的合法日期),并设置字段允许为`NULL`(如果业务允许)。 3. **在据访问层处理**:在查询时,通过SQL语句将非法日期转换为合法日期或`NULL`。例如,使用MySQL的`IF`或`CASE`语句: ```sql SELECT IF(update_time='0000-00-00 00:00:00', NULL, update_time) AS update_time, ... FROM table; ``` 或者使用MySQL的`NULLIF`函: ```sql SELECT NULLIF(update_time, '0000-00-00 00:00:00') AS update_time, ... FROM table; ``` 4. **在数据库连接字符串中添加参**(针对MySQL): 在JDBC连接URL中添加参`zeroDateTimeBehavior`,该参用于指定当遇到`0000-00-00`这样的日期时的处理方式。有以下几种选项: - `convertToNull`:转换为`NULL` - `round`:转换为最近的日期(如`0001-01-01`) - `exception`(默认):抛出异常 示例:在连接字符串中添加`zeroDateTimeBehavior=convertToNull` ``` jdbc:mysql://localhost:3306/dbname?zeroDateTimeBehavior=convertToNull ``` 这样,当查询到`0000-00-00`时,驱动会将其转换为`NULL`,从而避免异常。 5. **在MyBatis或MyBatis-Plus中自定义类型处理器**(TypeHandler): 可以编写一个自定义的`TypeHandler`,专门处理`java.sql.Timestamp`类型,当遇到`0000-00-00 00:00:00`时,将其转换为`null`或一个默认的合法日期。 示例自定义类型处理器: ```java @MappedTypes(Timestamp.class) public class CustomTimestampTypeHandler extends BaseTypeHandler<Timestamp> { @Override public void setNonNullParameter(PreparedStatement ps, int i, Timestamp parameter, JdbcType jdbcType) throws SQLException { ps.setTimestamp(i, parameter); } @Override public Timestamp getNullableResult(ResultSet rs, String columnName) throws SQLException { String dateTimeString = rs.getString(columnName); if ("0000-00-00 00:00:00".equals(dateTimeString)) { return null; } return rs.getTimestamp(columnName); } @Override public Timestamp getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String dateTimeString = rs.getString(columnIndex); if ("0000-00-00 00:00:00".equals(dateTimeString)) { return null; } return rs.getTimestamp(columnIndex); } @Override public Timestamp getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String dateTimeString = cs.getString(columnIndex); if ("0000-00-00 00:00:00".equals(dateTimeString)) { return null; } return cs.getTimestamp(columnIndex); } } ``` 然后,在MyBatis配置中注册这个处理器,或者在字段上通过`@TableField`注解指定: ```java @TableField(value = "update_time", typeHandler = CustomTimestampTypeHandler.class) private Timestamp updateTime; ``` 6. **使用MyBatis-Plus的字段自动填充功能**:如果不希望数据库中出现`0000-00-00 00:00:00`,可以在插入或更新时自动填充当前时间。这样可以避免非法值。但这种方法不能解决已有的非法值。 总结:建议优先考虑方案4(修改数据库连接字符串)或方案1(修改数据库中的据),因为这两种方法改动最小且最有效。如果无法修改数据库或连接字符串,则可以采用方案5(自定义类型处理器)来处理。 根据具体情况选择最合适的方案。 §§相关问题§§ 1. 如何修改MySQL中的非法日期值? 2. 如何在MyBatis-Plus中自定义类型处理器? 3. MySQL的JDBC连接字符串参`zeroDateTimeBehavior`还有哪些可选值? </think> ### 解决 `org.springframework.dao.TransientDataAccessResourceException` 错误的方法 该错误的核心问题是:数据库中的 `update_time` 字段值为 `0000-00-00 00:00:00`(非法时间戳),而 Java 的 `java.sql.Timestamp` 无法解析此值。以下是分步解决方案: --- ### 解决方案 #### 1. **修改数据库字段默认值(推荐)** - 将 `update_time` 的默认值改为合法的 `NULL` 或有效时间戳(如 `1970-01-01 00:00:01`): ```sql ALTER TABLE your_table MODIFY COLUMN update_time TIMESTAMP NULL DEFAULT NULL; ``` - **修复后效果**: 非法值 `0000-00-00` 被替换为 `NULL`,避免触发异常[^1]。 #### 2. **JDBC 连接参配置(快速修复)** - 在 MySQL 连接 URL 中添加参 `zeroDateTimeBehavior=convertToNull`: ```java jdbc:mysql://localhost:3306/db_name? zeroDateTimeBehavior=convertToNull&useSSL=false ``` - **作用**:自动将 `0000-00-00` 转为 `NULL`,而非抛出异常[^1]。 #### 3. **MyBatis-Plus 类型处理器(代码层修复)** - 创建自定义类型处理器 `CustomTimestampTypeHandler.java`: ```java public class CustomTimestampTypeHandler extends BaseTypeHandler<Timestamp> { @Override public void setNonNullParameter(...) { /* 正常设置 */ } @Override public Timestamp getNullableResult(ResultSet rs, String columnName) throws SQLException { String rawValue = rs.getString(columnName); if ("0000-00-00 00:00:00".equals(rawValue)) { return null; // 拦截非法值 } return rs.getTimestamp(columnName); } } ``` - 在实体类中指定处理器: ```java public class YourEntity { @TableField(typeHandler = CustomTimestampTypeHandler.class) private Timestamp updateTime; } ``` #### 4. **清理数据库非法据** - 修复现有非法据: ```sql UPDATE your_table SET update_time = NULL WHERE update_time = '0000-00-00 00:00:00'; ``` #### 5. **调整字段类型为 `DATETIME`** - 如果业务允许,改用更宽松的 `DATETIME` 类型: ```sql ALTER TABLE your_table MODIFY COLUMN update_time DATETIME DEFAULT NULL; ``` --- ### 原因分析 - MySQL 的 `TIMESTAMP` 类型取值范围为 `1970-01-01 00:00:01` 至 `2038-01-19 03:14:07`,`0000-00-00` 超出此范围。 - 当 MyBatis-Plus 尝试将非法值映射到 `java.sql.Timestamp` 时,触发 `SQLException`,最终抛出 Spring 的 `TransientDataAccessResourceException`[^1]。 --- ### 预防措施 1. 数据库设计时设置字段默认值为 `NULL` 或合法时间戳。 2. 启用 MyBatis-Plus 的自动填充功能,确保写入合法时间: ```java @TableField(fill = FieldFill.INSERT_UPDATE) private Timestamp updateTime; ``` 3. 在测试阶段插入边界值(如 `1970-01-01`)进行验证。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

niubility锐

觉得有用的话鼓励鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值