zoukankan      html  css  js  c++  java
  • 解决tinyint映射成boolean/byte的问题

    前言

    最近受疫情的影响,公司要做一个类似一码通的系统为客户服务。由我来进行表的设计。创建表之后需要逆向生成Java的entity、mapper、mapper.xml。由于我在数据库中定义了大量 tinyint(1) 的字段。在逆向的时候,默认生成的是Boolean类型的变量。而我们习惯于使用 Integer 作为tinyint的Java类型,这要怎么转换呢?因此这里就有两个问题需要解决:

    1. tinyint(1) 转换成数字类型而不是布尔类型
    2. tinyint(n) n>1 转换成 Integer 而非 Byte

    tinyint(1) 转换成数字类型

    在数据库连接url后面加上参数(建议复制,大小写错了不生效。多个keyvalue之间用 & 连接):

    tinyInt1isBit=false
    

    这一点在官方文档有说明:

    image-20200325094736352

    翻译过来就是:当字符类型为tinyint且长度为 1 时,会被转换成布尔类型。而虽然文档上说tinyInt1isBit取false时,转Integer。实际上转过来还是 Byte

    tinyint(n) n>1 转换成 Integer

    MyBatis Generator 是通过JavaTypeResolver 来实现关系映射的,官方文档解释

    image-20200325101610753

    在配置文件中有一个 <javaTypeResolver> 标签可以用来配置映射关系。而该标签有一个 type 属性。红色字体翻译过来就是:用户可以提供一个自定义的实现,该类必须实现JavaTypeResolver接口,且必须有一个共有的默认构造器,或者沿用默认值DEFAULT,将使用JavaTypeResolverDefaultImpl来进行映射,首先我们看一看它默认的实现类的构造方法

    public JavaTypeResolverDefaultImpl() {
        super();
        properties = new Properties();
        typeMap = new HashMap<>();
    
        // 此处省略其他字段的映射......
        typeMap.put(Types.TINYINT, new JdbcTypeInformation("TINYINT", //$NON-NLS-1$
                                                           new FullyQualifiedJavaType(Byte.class.getName())));
    
    }
    

    很明显,字段与Java的映射关系在构造方法中配置。我们改起来很简单,新建类继承 JavaTypeResolverDefaultImpl ,在子类构造方法中重新对 typeMap 赋值,利用 HashMap<> key相同value替换的性质替换默认的实现方式

    package other;
    
    import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
    import org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl;
    
    import java.sql.Types;
    
    public class MyTypeResolver extends JavaTypeResolverDefaultImpl {
    
        public MyTypeResolver() {
            super();
            typeMap.put(Types.TINYINT, new JavaTypeResolverDefaultImpl.JdbcTypeInformation("TINYINT", //$NON-NLS-1$
                    new FullyQualifiedJavaType(Integer.class.getName())));
        }
    }
    

    做完这些,将该类路径写在 type 中运行,你会发现该类无法被加载......

    打包类文件,被generator所依赖

    因为我所使用的generator是以Maven插件的形式集成到项目中的,插件启动的时候并不会加载我项目中的类文件。故会报类无法加载的错误。解决方法就是将该类文件打包,然后添加到插件的依赖中。如果你所在的公司项目中有公共的工具类项目可以直接在项目中写,上传到私服。如果没有,按照以下的步骤进行:

    1. 创建新项目,配好本地仓库地址
    2. 添加和你generator插件版本一样的generator依赖
    3. 新建类
    4. install

    这时你的工具类就已经发布到本地仓库了。此时在原来的插件中依赖该项目,并且排除generator的依赖。就可以正常生成Integer了:

    <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.27</version>
                </dependency>
                <dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.4.0</version>
                </dependency>
                <dependency>
                    <groupId>com.woke</groupId>
                    <artifactId>common</artifactId>
                    <version>1.0-SNAPSHOT</version>
                    <exclusions>
                        <exclusion>
                            <groupId>org.mybatis.generator</groupId>
                            <artifactId>mybatis-generator-core</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <id>Generate MyBatis Artifacts</id>
                    <phase>package</phase>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <!-- 允许移动生成的文件 -->
                <verbose>true</verbose>
                <!-- 是否覆盖 -->
                <overwrite>false</overwrite>
                <!-- 自动生成的配置 -->
                <configurationFile>
                    src/main/resources/mybatis-generator.xml</configurationFile>
            </configuration>
    </plugin>
    

    generator配置

    mybatis-generator.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
            PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
            "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    <generatorConfiguration>
        <!--mysql 连接数据库jar 这里选择自己本地位置-->
        <classPathEntry
                location="D:Applicationapache-maven-3.3.9localRepositorymysqlmysql-connector-java5.1.46mysql-connector-java-5.1.46.jar"/>
        <context id="testTables" targetRuntime="MyBatis3">
            <commentGenerator>
                <!-- 是否去除自动生成的注释 true:是 : false:否 -->
                <property name="suppressAllComments" value="true"/>
            </commentGenerator>
            <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
            <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                            connectionURL="jdbc:mysql://localhost:3306/woke_cloud_property?serverTimezone=UTC&amp;tinyInt1isBit=false"
                            userId="root"
                            password="root">
            </jdbcConnection>
            <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
               NUMERIC 类型解析为java.math.BigDecimal -->
    
            <javaTypeResolver type="other.MyTypeResolver">
                <property name="forceBigDecimals" value="false"/>
            </javaTypeResolver>
    
            <!-- targetProject:生成PO类的位置 -->
            <javaModelGenerator targetPackage="cn.keats.project.camp.entity"
                                targetProject="src/main/java">
                <!-- enableSubPackages:是否让schema作为包的后缀 -->
                <property name="enableSubPackages" value="false"/>
                <!-- 从数据库返回的值被清理前后的空格 -->
                <property name="trimStrings" value="true"/>
            </javaModelGenerator>
            <!-- targetProject:mapper映射文件生成的位置
               如果maven工程只是单独的一个工程,targetProject="src/main/java"
               若果maven工程是分模块的工程,targetProject="所属模块的名称",例如:
               targetProject="ecps-manager-mapper",下同-->
            <sqlMapGenerator targetPackage="mapper"
                             targetProject="src/main/resources">
                <!-- enableSubPackages:是否让schema作为包的后缀 -->
                <property name="enableSubPackages" value="false"/>
            </sqlMapGenerator>
            <!-- targetPackage:mapper接口生成的位置 -->
            <javaClientGenerator type="XMLMAPPER"
                                 targetPackage="cn.keats.project.camp.mapper"
                                 targetProject="src/main/java">
                <!-- enableSubPackages:是否让schema作为包的后缀 -->
                <property name="enableSubPackages" value="false"/>
            </javaClientGenerator>
            <!-- 指定数据库表  多个表示,可用多个table标签-->
            <table tableName="test_tinyint"
                   enableCountByExample="false"
                   enableUpdateByExample="false"
                   enableDeleteByExample="false"
                   enableSelectByExample="false"
                   selectByExampleQueryId="false">
            </table>
        </context>
    </generatorConfiguration>
    
    

    其他逆向工程的工具

    easycode通过IDEA连接数据库后,可以使用右键直接生成,高度定制化

    mybaits plus 设置起来和 generator 差不多,不过方便的是可以在main方法直接设置:

    // 重写Mysql关于字段类型的转换配置
    dsc.setTypeConvert((globalConfig, 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.INTEGER;
        } 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")) {
            return DbColumnType.STRING;
        } else if (t.contains("date") || t.contains("time") || t.contains("year")) {
            switch (globalConfig.getDateType()) {
                case ONLY_DATE:
                    return DbColumnType.DATE;
                case SQL_PACK:
                    switch (t) {
                        case "date":
                            return DbColumnType.DATE_SQL;
                        case "time":
                            return DbColumnType.TIME;
                        case "year":
                            return DbColumnType.DATE_SQL;
                        default:
                            return DbColumnType.TIMESTAMP;
                    }
                case TIME_PACK:
                    switch (t) {
                        case "date":
                            return DbColumnType.LOCAL_DATE;
                        case "time":
                            return DbColumnType.LOCAL_TIME;
                        case "year":
                            return DbColumnType.YEAR;
                        default:
                            return DbColumnType.LOCAL_DATE_TIME;
                    }
            }
        }
        return DbColumnType.STRING;
    });
    mpg.setDataSource(dsc);
    
  • 相关阅读:
    典型的 C++ 程序员成长经历
    C语言中的常用文件操作
    sscanf与正则表达式
    黑莓8700 常用快捷键
    [分享]《张靓颖个人资源汇集.九月二日更新》
    [分享]【★超级女声★】【★张靓颖★】【推荐】
    [原创]根据TreeView中节点的不同,来绑定不同的dropdownlist
    [转贴]用Vs.net制作安装程序,在安装包中自动为客户创建数据库
    [转贴]在Asp.Net中的几种事务处理的方法
    冻结DataGrid中的列的比较简单的实现方法!
  • 原文地址:https://www.cnblogs.com/keatsCoder/p/12564758.html
Copyright © 2011-2022 走看看