解决tinyint映射成boolean/byte的问题
作者:@后青春期的Keats
本文为作者原创,转载请注明出处:https://www.cnblogs.com/keatsCoder/p/12564758.html
## 前言
最近受疫情的影响,公司要做一个类似一码通的系统为客户服务。由我来进行表的设计。创建表之后需要逆向生成Java的entity、mapper、mapper.xml。由于我在数据库中定义了大量 tinyint(1) 的字段。在逆向的时候,默认生成的是Boolean类型的变量。而我们习惯于使用 Integer 作为tinyint的Java类型,这要怎么转换呢?因此这里就有两个问题需要解决:
- tinyint(1) 转换成数字类型而不是布尔类型
- tinyint(n) n>1 转换成 Integer 而非 Byte
tinyint(1) 转换成数字类型
在数据库连接url后面加上参数(建议复制,大小写错了不生效。多个keyvalue之间用 & 连接):
tinyInt1isBit=false
这一点在官方文档有说明:
翻译过来就是:当字符类型为tinyint且长度为 1 时,会被转换成布尔类型。而虽然文档上说tinyInt1isBit取false时,转Integer。实际上转过来还是 Byte
tinyint(n) n>1 转换成 Integer
MyBatis Generator 是通过JavaTypeResolver 来实现关系映射的,官方文档解释
在配置文件中有一个 <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插件的形式集成到项目中的,插件启动的时候并不会加载我项目中的类文件。故会报类无法加载的错误。解决方法就是将该类文件打包,然后添加到插件的依赖中。如果你所在的公司项目中有公共的工具类项目可以直接在项目中写,上传到私服。如果没有,按照以下的步骤进行:
- 创建新项目,配好本地仓库地址
- 添加和你generator插件版本一样的generator依赖
- 新建类
- 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:\Application\apache-maven-3.3.9\localRepository\mysql\mysql-connector-java\5.1.46\mysql-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&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);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端