问题描述:
Cannot convert string 'aaa' to java.sql.Timestamp value; nested exception is java.sql.SQLDataException: Cannot convert string 'aaa' to java.sql.Timestamp value
at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:84)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:74)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)
at com.sun.proxy.$Proxy134.selectOne(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:159)
原因排查:
这里为什么会把 string 转换位 Timestamp呢?
表结构实体类:
@Builder
@Data
@Accessors(chain = true)
@ApiModel(value="TTest对象", description="")
@TableName("t_test")
public class TTest implements Serializable {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "name")
@TableField("name")
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@ApiModelProperty(value = "创建时间")
@TableField("create_time")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@ApiModelProperty(value = "最后一次修改时间")
@TableField("update_time")
private Date updateTime;
}
按照字段顺序,生成了一个构造方法。查看mybatis的源码,查询结果进行映射时,就是根据这个构造方法进行数据映射的。
代码截图片段对应的方法:
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#createUsingConstructor
mybatis生成的 sql语句是:
这个sql的查询字段的顺序,是在项目启动时就已经生成的。具体为什么这样生成?还没研究。
代码截图对应的代码:
org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
查询结果中,第二个数据是 create_time,构造方法第二个参数是 String。所以发生了类型转换异常。
解决方案:
由于生成的查询字段顺序不确定,就不能使用构造方法来进行映射。所以只要没有带参数的构造方法就可以了。我这里之所以生成了构造方法,是因为使用了 @Builder 注解。把这个注解去掉就OK 了。