我们在使用mybatis generator生成实体类的时候,可以使用元素javaTypeResolver来指定JDBC类型和Java类型的转换关系。
该元素提供了一个可选的属性type,和<commentGenerator>比较类型,提供了默认的实现DEFAULT(org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl),一般情况下使用默认即可,需要特殊处理的情况可以通过其他元素配置来解决,不建议修改该属性。
该属性还有一个可以配置的<property>元素。
可以配置的属性为forceBigDecimals,该属性可以控制是否强制DECIMAL和NUMERIC类型的字段转换为Java类型的java.math.BigDecimal,默认值为false,一般不需要配置。
默认情况下的转换规则为:
如果精度>0或者长度>18,就会使用java.math.BigDecimal
如果精度=0并且10<=长度<=18,就会使用java.lang.Long
如果精度=0并且5<=长度<=9,就会使用java.lang.Integer
如果精度=0并且长度<5,就会使用java.lang.Short
如果设置为true,那么一定会使用java.math.BigDecimal。
但是我们平时的实体类中,不管精度如何,都统一使用java.lang.Long。所以这里就需要我们自定义javaTypeResolver。
generatorConfig.xml中设置如下:
<!--指定生成的类型为java类型,避免数据库中number等类型字段 -->
<javaTypeResolver type ="com.ztesoft.zsmart.bss.prov.common.util.MyJavaTypeResolver">
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
自定义的com.ztesoft.zsmart.bss.prov.common.util.MyJavaTypeResolver,改了calculateBigDecimalReplacement方法:
/****************************************************************************************
Copyright © 2003-2012 ZTEsoft Corporation. All rights reserved. Reproduction or <br>
transmission in whole or in part, in any form or by any means, electronic, mechanical <br>
or otherwise, is prohibited without the prior written consent of the copyright owner. <br>
****************************************************************************************/
package com.ztesoft.zsmart.bss.prov.common.util;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.JavaTypeResolver;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.internal.util.StringUtility;
/**
* <Description> <br>
*
* @author luoluocaihong<br>
* @version 1.0<br>
* @taskId <br>
* @CreateDate Nov 23, 2017 <br>
* @since R9.0<br>
* @see com.ztesoft.zsmart.bss.prov.common.util <br>
*/
public class MyJavaTypeResolver implements JavaTypeResolver {
/**
* warnings<br>
*/
protected List<String> warnings;
/**
* properties <br>
*/
protected Properties properties;
/**
* context<br>
*/
protected Context context;
/**
* forceBigDecimals<br>
*/
protected boolean forceBigDecimals;
/**
* typeMap<br>
*/
protected Map<Integer, JdbcTypeInformation> typeMap;
/**
* <br>
*/
public MyJavaTypeResolver() {
this.properties = new Properties();
this.typeMap = new HashMap<Integer, JdbcTypeInformation>();
this.typeMap.put(Integer.valueOf(2003), new JdbcTypeInformation("ARRAY", new FullyQualifiedJavaType(
Object.class.getName())));
this.typeMap.put(Integer.valueOf(-5),
new JdbcTypeInformation("BIGINT", new FullyQualifiedJavaType(Long.class.getName())));
this.typeMap.put(Integer.valueOf(-2), new JdbcTypeInformation("BINARY", new FullyQualifiedJavaType("byte[]")));
this.typeMap.put(Integer.valueOf(-7),
new JdbcTypeInformation("BIT", new FullyQualifiedJavaType(Boolean.class.getName())));
this.typeMap.put(Integer.valueOf(2004), new JdbcTypeInformation("BLOB", new FullyQualifiedJavaType("byte[]")));
this.typeMap.put(Integer.valueOf(16), new JdbcTypeInformation("BOOLEAN", new FullyQualifiedJavaType(
Boolean.class.getName())));
this.typeMap.put(Integer.valueOf(1),
new JdbcTypeInformation("CHAR", new FullyQualifiedJavaType(String.class.getName())));
this.typeMap.put(Integer.valueOf(2005),
new JdbcTypeInformation("CLOB", new FullyQualifiedJavaType(String.class.getName())));
this.typeMap.put(Integer.valueOf(70), new JdbcTypeInformation("DATALINK", new FullyQualifiedJavaType(
Object.class.getName())));
this.typeMap.put(Integer.valueOf(91),
new JdbcTypeInformation("DATE", new FullyQualifiedJavaType(Date.class.getName())));
this.typeMap.put(Integer.valueOf(3), new JdbcTypeInformation("DECIMAL", new FullyQualifiedJavaType(
BigDecimal.class.getName())));
this.typeMap.put(Integer.valueOf(2001), new JdbcTypeInformation("DISTINCT", new FullyQualifiedJavaType(
Object.class.getName())));
this.typeMap.put(Integer.valueOf(8),
new JdbcTypeInformation("DOUBLE", new FullyQualifiedJavaType(Double.class.getName())));
this.typeMap.put(Integer.valueOf(6),
new JdbcTypeInformation("FLOAT", new FullyQualifiedJavaType(Double.class.getName())));
this.typeMap.put(Integer.valueOf(4), new JdbcTypeInformation("INTEGER", new FullyQualifiedJavaType(
Integer.class.getName())));
this.typeMap.put(Integer.valueOf(2000), new JdbcTypeInformation("JAVA_OBJECT", new FullyQualifiedJavaType(
Object.class.getName())));
this.typeMap.put(Integer.valueOf(-16), new JdbcTypeInformation("LONGNVARCHAR", new FullyQualifiedJavaType(
String.class.getName())));
this.typeMap.put(Integer.valueOf(-4), new JdbcTypeInformation("LONGVARBINARY", new FullyQualifiedJavaType(
"byte[]")));
this.typeMap.put(Integer.valueOf(-1), new JdbcTypeInformation("LONGVARCHAR", new FullyQualifiedJavaType(
String.class.getName())));
this.typeMap.put(Integer.valueOf(-15),
new JdbcTypeInformation("NCHAR", new FullyQualifiedJavaType(String.class.getName())));
this.typeMap.put(Integer.valueOf(2011), new JdbcTypeInformation("NCLOB", new FullyQualifiedJavaType(
String.class.getName())));
this.typeMap.put(Integer.valueOf(-9), new JdbcTypeInformation("NVARCHAR", new FullyQualifiedJavaType(
String.class.getName())));
this.typeMap.put(Integer.valueOf(0),
new JdbcTypeInformation("NULL", new FullyQualifiedJavaType(Object.class.getName())));
this.typeMap.put(Integer.valueOf(2), new JdbcTypeInformation("NUMERIC", new FullyQualifiedJavaType(
BigDecimal.class.getName())));
this.typeMap.put(Integer.valueOf(1111), new JdbcTypeInformation("OTHER", new FullyQualifiedJavaType(
Object.class.getName())));
this.typeMap.put(Integer.valueOf(7),
new JdbcTypeInformation("REAL", new FullyQualifiedJavaType(Float.class.getName())));
this.typeMap.put(Integer.valueOf(2006),
new JdbcTypeInformation("REF", new FullyQualifiedJavaType(Object.class.getName())));
this.typeMap.put(Integer.valueOf(5),
new JdbcTypeInformation("SMALLINT", new FullyQualifiedJavaType(Short.class.getName())));
this.typeMap.put(Integer.valueOf(2002), new JdbcTypeInformation("STRUCT", new FullyQualifiedJavaType(
Object.class.getName())));
this.typeMap.put(Integer.valueOf(92),
new JdbcTypeInformation("TIME", new FullyQualifiedJavaType(Date.class.getName())));
this.typeMap.put(Integer.valueOf(93), new JdbcTypeInformation("TIMESTAMP", new FullyQualifiedJavaType(
Date.class.getName())));
this.typeMap.put(Integer.valueOf(-6),
new JdbcTypeInformation("TINYINT", new FullyQualifiedJavaType(Byte.class.getName())));
this.typeMap.put(Integer.valueOf(-3),
new JdbcTypeInformation("VARBINARY", new FullyQualifiedJavaType("byte[]")));
this.typeMap.put(Integer.valueOf(12), new JdbcTypeInformation("VARCHAR", new FullyQualifiedJavaType(
String.class.getName())));
}
/**
*
* Description: <br>
*
* @author luoluocaihong<br>
* @taskId <br>
* @param properties Properties<br>
*/
public void addConfigurationProperties(Properties properties) {
this.properties.putAll(properties);
this.forceBigDecimals = StringUtility.isTrue(properties.getProperty("forceBigDecimals"));
}
/**
*
* Description: <br>
*
* @author luoluocaihong<br>
* @taskId <br>
* @param introspectedColumn IntrospectedColumn
* @return <br>
*/
public FullyQualifiedJavaType calculateJavaType(IntrospectedColumn introspectedColumn) {
FullyQualifiedJavaType answer = null;
JdbcTypeInformation jdbcTypeInformation = (JdbcTypeInformation) this.typeMap.get(Integer
.valueOf(introspectedColumn.getJdbcType()));
if (jdbcTypeInformation != null) {
answer = jdbcTypeInformation.getFullyQualifiedJavaType();
answer = overrideDefaultType(introspectedColumn, answer);
}
return answer;
}
/**
*
* Description: <br>
*
* @author luoluocaihong<br>
* @taskId <br>
* @param column IntrospectedColumn
* @param defaultType FullyQualifiedJavaType
* @return FullyQualifiedJavaType<br>
*/
protected FullyQualifiedJavaType overrideDefaultType(IntrospectedColumn column, FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer = defaultType;
switch (column.getJdbcType()) {
case -7:
answer = calculateBitReplacement(column, defaultType);
break;
case 2:
case 3:
answer = calculateBigDecimalReplacement(column, defaultType);
default:
answer = answer;
}
return answer;
}
/**
*
* Description: <br>
*
* @author luoluocaihong<br>
* @taskId <br>
* @param column IntrospectedColumn
* @param defaultType FullyQualifiedJavaType
* @return <br>
*/
protected FullyQualifiedJavaType calculateBitReplacement(IntrospectedColumn column,
FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer;
if (column.getLength() > 1) {
answer = new FullyQualifiedJavaType("byte[]");
}
else {
answer = defaultType;
}
return answer;
}
/**
*
* Description: <br>
*
* @author luoluocaihong<br>
* @taskId <br>
* @param column IntrospectedColumn
* @param defaultType FullyQualifiedJavaType
* @return <br>
*/
protected FullyQualifiedJavaType calculateBigDecimalReplacement(IntrospectedColumn column,
FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer;
// if ((column.getScale() > 0) || (column.getLength() > 18) || (this.forceBigDecimals))
// answer = defaultType;
// else if (column.getLength() > 9)
// answer = new FullyQualifiedJavaType(Long.class.getName());
// else if (column.getLength() > 4)
// answer = new FullyQualifiedJavaType(Integer.class.getName());
// else {
// answer = new FullyQualifiedJavaType(Short.class.getName());
// }
answer = new FullyQualifiedJavaType(Long.class.getName());
return answer;
}
/**
*
* Description: <br>
*
* @author luoluocaihong<br>
* @taskId <br>
* @param introspectedColumn IntrospectedColumn <br>
* @return <br>
*/
public String calculateJdbcTypeName(IntrospectedColumn introspectedColumn) {
String answer = null;
JdbcTypeInformation jdbcTypeInformation = (JdbcTypeInformation) this.typeMap.get(Integer
.valueOf(introspectedColumn.getJdbcType()));
if (jdbcTypeInformation != null) {
answer = jdbcTypeInformation.getJdbcTypeName();
}
return answer;
}
public void setWarnings(List<String> warnings) {
this.warnings = warnings;
}
public void setContext(Context context) {
this.context = context;
}
/**
*
* <Description> <br>
*
* @author luoluocaihong<br>
* @version 1.0<br>
* @taskId <br>
* @CreateDate Nov 23, 2017 <br>
* @since R9.0<br>
* @see com.ztesoft.zsmart.bss.prov.common.util <br>
*/
public static class JdbcTypeInformation {
/**
* jdbcTypeName<br>
*/
private String jdbcTypeName;
/**
* fullyQualifiedJavaType<br>
*/
private FullyQualifiedJavaType fullyQualifiedJavaType;
/**
* <br>
* @param jdbcTypeName String
* @param fullyQualifiedJavaType FullyQualifiedJavaType
*/
public JdbcTypeInformation(String jdbcTypeName, FullyQualifiedJavaType fullyQualifiedJavaType) {
this.jdbcTypeName = jdbcTypeName;
this.fullyQualifiedJavaType = fullyQualifiedJavaType;
}
public String getJdbcTypeName() {
return this.jdbcTypeName;
}
public FullyQualifiedJavaType getFullyQualifiedJavaType() {
return this.fullyQualifiedJavaType;
}
}
}
pom.xml中配置如下:
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<id>Generate MyBatis Files</id>
<goals>
<goal>generate</goal>
</goals>
<phase>generate</phase>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</execution>
</executions>
<dependencies>
<!--
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>-->
<dependency>
<groupId>com.ztesoft.zsmart.bss.prov</groupId>
<artifactId>prov-common</artifactId>
<version>9.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.ztesoft.zsmart.core</groupId>
<artifactId>core-boot-starter-oracle</artifactId>
<version>9.0.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
需要注意的是,自定义javaTypeResolver,需要在插件mybatis-generator-maven-plugin中通过dependency将自定义类所在的jar依赖进来。不然会报错Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2:generate (default-cli) on project prov-common: Execution default-cli of goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2:generate failed: Cannot instantiate object of type com.ztesoft.zsmart.bss.prov.common.util.MyJavaTypeResolver -> [Help 1]
日志如下:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building prov-common 9.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- mybatis-generator-maven-plugin:1.3.2:generate (default-cli) @ prov-common ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.732s
[INFO] Finished at: Thu Nov 23 19:54:02 GMT+08:00 2017
[INFO] Final Memory: 10M/150M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2:generate (default-cli) on project prov-common: Execution default-cli of goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2:generate failed: Cannot instantiate object of type com.ztesoft.zsmart.bss.prov.common.util.MyJavaTypeResolver -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException