前言
今天遇上这样的一个情况,数据库类型与Java对象属性类型不对应,这种情况该如何处理
在 MySQL 中,字段的属性为 BigInt
,按道理来说,对应Java
中的Long
类型。
但实际上项目中与之对应的 Java对象中的属性的类型是 Date
类型,直接给我这个废物当头一棒
而且不是一两张表,是比较多的表处于Date
和 BigInt
混用的情况,
你说要好好用Date就好好用Date,要好好用时间戳就好好用时间戳啊,还混用,类型还不对应,麻了
(别问这个项目怎么出现这种事情的,就是来了人,又走了人,然后填坑)
保持微笑😀(此处口吐芬芳xxxxxx)
一、思考
我想知道出现这种情况,你是如何思考的?
我的思考是,到底是改数据库,还是改程序代码比较好。
但是无论哪一种我都不敢轻举妄动,所以我做的第一步是把数据库和代码备份,确保不会被玩坏。
我也问了同事,他的建议是让我改程序。
但是怎么说勒,我细细比较了改代码和改程序的麻烦程度,改数据表麻烦会少很多,我就在表结构中的Bigint 类型改为 datatime 类型,而且当时我的任务,是只局限于一两张业务表,影响范围不大,引用也不多。
我就兴冲冲的把表结构改了,然后把任务完成了~
等到今天上午,我之前询问的那个同事也遇到这个问题,他就向上面的经理提了一嘴,说时间类型不对,问他标准是哪一种,经理说是时间戳,我心里一凉~,麻了,(此处省略一万句)
听完,我就苦逼的把表结构改回来了,此时备份就发生作用了~
还原完数据表后,我就打算去改程序代码了
周一写 bug,bug 改一周
突然他和我聊到,xxx,你知道MybatisPlus,有什么方法可以做这种转换吗?
这每一个都要改,太麻烦了,而且业务代码中肯定也用到了,这改起来代价太大了,有没有注解的方式可以解决转换问题。
很浅显的思考,但是我能够感觉到自己的经验的不足,对于很多偷懒(思考),我还是差的太远了。
二、解决方式
因为用到的 ORM 框架是 MybatisPlus,所以首先找的就是有没有官方的支持。
继而就在官网找到一个字段类型处理器,一看才发现,是学过的东西啊,只怪用的太少,知道的太少啊。
然后根据这个线索继续找,就了解到 MyBatis-Plus 字段类型处理器 TypeHandler
这个 TypeHandler 处于的位置,就是应用程序和数据库之间的拦截器,所有的操作,都会走一遍这里。
就翻看源码,想用一个东西,最快的方式就是看一下源码的实现
2.1、TypeHandler源码
public interface TypeHandler<T> {
/**
* 入库前的类型转换
*/
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
/**
* 得到结果。
* 查询后的数据处理
*/
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
复制代码
找到接口,看一下源码中针对已有属性是如何处理,我们仿写一份,达到我们的要求即可啊.
2.2、BaseTypeHandler 源码
有这么多,我们直接看一下 BaseTypeHandler
是什么样的处理逻辑,
一方面 base 吗,基础吗,我们就看看基础是什么样的处理啦,另外一方面他是抽象类吗,说明它其他实现类的基类吗。
public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {
@Override
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
if (jdbcType == null) {
throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {
ps.setNull(i, jdbcType.TYPE_CODE);
} catch (SQLException e) {
throw new TypeException("Error setting null for parameter #" + i + " wit