项目场景:
项目场景:当数据库中的字段类型和java实体类型不匹配时,mybatis将字段映射到实体属性上会出现一些转换异常
初始问题描述
比如在实体中存在一个Date类型的属性date
在sql表中存在对应的字段
但是在sql表中,该数据的类型为bigInt,存储的是1970年1月1日00:00:00到目标时间的毫秒数。
当你使用mybatis将表中的数据映射到实体中时,就会出现转换异常
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'birthday' from result set. Cause: java.sql.SQLDataException: Unsupported conversion from LONG to java.sql.Timestamp
初始问题解决
1.此时我们可以使用mybatis的TypeHandler进行类型转换处理(注意!!!!!!!此时这个handler是为了将数据库中的birthday(bigInt型)转换成java实体中的birthday(util.date型))
package com.itheima.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
/**
* @author Watching
* * @date 2022/5/11
* * Describe:
*/
public class DateTypeHandler extends BaseTypeHandler<Date> {
//将java类型转换成数据需要的类型
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
long time = date.getTime();
preparedStatement.setLong(i, time);//i是参数位置
System.out.println("setNonNullParameter将java类型转换成数据需要的类型");
}
//将数据库中的类型转换成java类型
//String参数 要转换的字段名称
//ResultSet 查询出的结果集
public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
System.out.println(s);
long aLong = resultSet.getLong(s);
Date date = new Date(aLong);
System.out.println("getNullableResult将数据库中的类型转换成java类型");
return date;
}
//将数据库中的类型转换成java类型
public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
long aLong = resultSet.getLong(i);
Date date = new Date(aLong);
System.out.println("getNullableResult将数据库中的类型转换成java类型");
return date;
}
public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
long aLong = callableStatement.getLong(i);
Date date = new Date(aLong);
System.out.println("getNullableResult");
return date;
}
}
2.并且在mybatis核心文件中注册TypeHandler
<!--注册类型转换驱动 也可以选择不在mybatis核心配置文件中配置(在核心文件中配置为全局配置,所有实体中符合BaseTypeHandler<T>中T类型的属性都会被转换),而在mapper配置文件中的某个特定字段上配置 避免某些实体中的属性符合转换要求但是实际上又不需要转换导致的异常-->
<typeHandlers>
<typeHandler handler="com.itheima.handler.DateTypeHandler"/>
</typeHandlers>
3.此时再测试就可以获得成功结果啦
进阶问题
如果查询的表中的某个字段对应的实体属性符合BaseTypeHandler,但是该字段在数据库中的数据类型又不是bigInt,如
数据库中的ordertime是datetime类型
此时执行查询操作就会出现新的异常
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'ordertime' from result set. Cause: java.sql.SQLDataException: Unsupported conversion from DATETIME to java.lang.Long
为什么会出现这个异常呢? 因为我们上面的自定义TypeHandler的功能是将bigInt转换为util.Date
而此时该字段的类型为datetime
进阶问题解决:
1.将mybatis核心文件中的TypeHandler注册注释掉
2.在特定的字段上进行TypeHandler的注册
此时mybatis就只会对你指定的实体属性和字段进行转换,不会对所有符合的实体属性和字段就行转换
3.得到正确结果