使用MyBatisPlus代码生成和druid集成的问题

错误日志如下:

2020-07-29 17:46:47.767 ERROR 6976 --- [nio-8553-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Error attempting to get column 'create_time' from result set.  Cause: java.sql.SQLFeatureNotSupportedException
; null; nested exception is java.sql.SQLFeatureNotSupportedException] with root cause

java.sql.SQLFeatureNotSupportedException: null

产生原因: 在mybatisplus的代码生成器中将数据库的datetime类型转换成为LocalDateTime, 集成druid数据源,使用3.1.0之前版本没问题,升级mp到3.1.1+后,运行时报错:java.sql.SQLFeatureNotSupportedException, 原因: mp3.1.1+使用了新版jdbc,LocalDateTime等新日期类型处理方式升级,但druid不支持,参考:苞米豆的Git

依赖版本

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

解决方案(三种):

  1. 在全局配置中设置dateType:
gc.setDateType(DateType.ONLY_DATE);
  1. 在数据源配置中进行类型转换
DataSourceConfig dsc = new DataSourceConfig();
dsc.setTypeConvert(new MySqlTypeConvert() {
    // 自定义数据库表字段类型转换【可选】
    @Override
    public DbColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
        System.out.println("转换类型:" + fieldType);
        //将数据库中datetime转换成date
        if ( fieldType.toLowerCase().contains( "datetime" ) ) {
            return DbColumnType.DATE;
        }
        return (DbColumnType) super.processTypeConvert(globalConfig, fieldType);
    }
});
  1. 提高德鲁伊的版本1.1.18(不过因为一处有问题而更改项目依赖的版本总归是不太好的)

解析前两种解决方案

// 代码生成器对象
AutoGenerator mpg = new AutoGenerator();
// 数据源配置对象
DataSourceConfig dsc = new DataSourceConfig();
// 显示进行类型转换
dsc.setTypeConvert(new MySqlTypeConvert() {
    // 自定义数据库表字段类型转换【可选】
    @Override
    public DbColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
        System.out.println("转换类型:" + fieldType);
        //将数据库中datetime转换成date
        if ( fieldType.toLowerCase().contains( "datetime" ) ) {
            return DbColumnType.DATE;
        }
        return (DbColumnType) super.processTypeConvert(globalConfig, fieldType);
    }
});
// 设置数据源配置
mpg.setDataSource(dsc);

setDataSource(final DataSourceConfig dataSource)源码

// 返回一个AutoGenerator对象
public AutoGenerator setDataSource(final DataSourceConfig dataSource) {
    this.dataSource = dataSource;
    return this;
}
// AutoGenerator类的属性
private DataSourceConfig dataSource; // 数据源配置

// DataSourceConfig类中有类型转换的接口属性
private ITypeConvert typeConvert;

ITypeConvert接口源码

public interface ITypeConvert {
    default IColumnType processTypeConvert(GlobalConfig globalConfig, TableField tableField) {
        return this.processTypeConvert(globalConfig, tableField.getType());
    }

    IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType);
}

processTypeConvert方法实现

public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
    String t = fieldType.toLowerCase();
    if (t.contains("char")) {
        return DbColumnType.STRING;
    } else if (t.contains("bigint")) {
        return DbColumnType.LONG;
    } else if (t.contains("tinyint(1)")) {
        return DbColumnType.BOOLEAN;
    } else if (t.contains("int")) {
        return DbColumnType.INTEGER;
    } else if (t.contains("text")) {
        return DbColumnType.STRING;
    } else if (t.contains("bit")) {
        return DbColumnType.BOOLEAN;
    } else if (t.contains("decimal")) {
        return DbColumnType.BIG_DECIMAL;
    } else if (t.contains("clob")) {
        return DbColumnType.CLOB;
    } else if (t.contains("blob")) {
        return DbColumnType.BLOB;
    } else if (t.contains("binary")) {
        return DbColumnType.BYTE_ARRAY;
    } else if (t.contains("float")) {
        return DbColumnType.FLOAT;
    } else if (t.contains("double")) {
        return DbColumnType.DOUBLE;
    } else if (!t.contains("json") && !t.contains("enum")) {
        if (t.contains("date") || t.contains("time") || t.contains("year")) {
            byte var5;
            switch(globalConfig.getDateType()) {
            case ONLY_DATE:
                return DbColumnType.DATE;
            case SQL_PACK:
                var5 = -1;
                switch(t.hashCode()) {
                case 3076014:
                    if (t.equals("date")) {
                        var5 = 0;
                    }
                    break;
                case 3560141:
                    if (t.equals("time")) {
                        var5 = 1;
                    }
                    break;
                case 3704893:
                    if (t.equals("year")) {
                        var5 = 2;
                    }
                }

                switch(var5) {
                case 0:
                    return DbColumnType.DATE_SQL;
                case 1:
                    return DbColumnType.TIME;
                case 2:
                    return DbColumnType.DATE_SQL;
                default:
                    return DbColumnType.TIMESTAMP;
                }
            case TIME_PACK:
                var5 = -1;
                switch(t.hashCode()) {
                case 3076014:
                    if (t.equals("date")) {
                        var5 = 0;
                    }
                    break;
                case 3560141:
                    if (t.equals("time")) {
                        var5 = 1;
                    }
                    break;
                case 3704893:
                    if (t.equals("year")) {
                        var5 = 2;
                    }
                }

                switch(var5) {
                case 0:
                    return DbColumnType.LOCAL_DATE;
                case 1:
                    return DbColumnType.LOCAL_TIME;
                case 2:
                    return DbColumnType.YEAR;
                default:
                    return DbColumnType.LOCAL_DATE_TIME;
                }
            }
        }

        return DbColumnType.STRING;
    } else {
        return DbColumnType.STRING;
    }
}

在processTypeConvert方法的实现中其实就是判断需要转换的类型是否存在, 是什么类型,如果不存在,mp的将默认将类型转换为DbColumnType.LOCAL_DATE_TIME;

“LocalDateTime”==> “java.time.LocalDateTime”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值