2019-02-22
配置文件:
pom.xml 添加 dependency plugin 基於mybatis-plus

<dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.6</version> <scope>compile</scope> </dependency>

<plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.6</version> <configuration> <!--配置文件的位置--> <configurationFile>generator.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> <executions> <execution> <id>Generate MyBatis Artifacts</id> <phase>deploy</phase> <goals> <goal>generate</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.6</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0.3</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>my.base.project</groupId> <artifactId>base-core</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </plugin>
generatorConfiguration.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> <!-- 引入配置文件 --> <properties resource="generator.properties" /> <context id="default" targetRuntime="MyBatis3"> <!-- 生成的Java文件的編碼 --> <property name="javaFileEncoding" value="UTF-8" /> <!-- 格式化java代碼 --> <property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter" /> <!-- 使用自定義的插件 --> <!-- 整合lombok --> <plugin type="*.support.GeneratorPlugin"/> <commentGenerator> <!-- 關閉自動生成的注釋 --> <property name="suppressAllComments" value="true"/> <!--生成的注釋包含時間戳--> <property name="suppressDate" value="true"/> </commentGenerator> <!--數據庫連接的信息:驅動類、連接地址、用戶名、密碼 --> <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"> <!-- 字段注解 針對oracle數據庫 --> <property name="remarksReporting" value="true" /> <!-- 字段注解 針對mysql數據庫 --> <property name="useInformationSchema" value="true"/> </jdbcConnection> <!-- 類型轉換 --> <javaTypeResolver> <!-- 是否使用bigDecimal 默認false:把JDBC DECIMAL 和 NUMERIC 類型解析為 Integer, 為 true時:把JDBC DECIMAL 和 NUMERIC 類型解析為java.math.BigDecimal --> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- 生成實體類 --> <!-- targetPackage:生成實體類的包名 --> <!-- targetProject:生成PO類的位置 --> <javaModelGenerator targetPackage="${model.package}" targetProject="${target.project}/java"> <!--所有實體類繼承BasePojo類--> <property name="rootClass" value="*.base.BaseModel"/> <!-- enableSubPackages:是否讓schema作為包的后綴 --> <property name="enableSubPackages" value="false"/> <!-- 從數據庫返回的值被清理前后的空格 --> <property name="trimStrings" value="false"/> </javaModelGenerator> <!-- 生成XxxMapper.xml文件 --> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="${xml.mapper.package}" targetProject="${target.project}/resources"> <!-- enableSubPackages:是否讓schema作為包的后綴 --> <property name="enableSubPackages" value="false"/> </sqlMapGenerator> <!-- 生成XxxMapper.java文件 --> <!--ANNOTATEDMAPPER: 生成java類文件,基於注解的Mapper接口,不會有對應的XML映射文件 MIXEDMAPPER:XML和注解的混合形式 XMLMAPPER:所有的方法都在XML中,接口調用依賴XML文件 --> <javaClientGenerator type="XMLMAPPER" targetPackage="${mapper.package}" targetProject="${target.project}/java"> <property name="enableSubPackages" value="false"/> </javaClientGenerator> <table schema="JTP" tableName="${table.name}" domainObjectName="${table.domainObjectName}" enableSelectByPrimaryKey="true" enableInsert="false" enableUpdateByPrimaryKey="false" enableDeleteByPrimaryKey="false" enableSelectByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableCountByExample="false" selectByExampleQueryId="false"> </table> </context> </generatorConfiguration>
generator.properties config 使用的參數

# 數據庫連接配置
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@ip:orcl
jdbc.username=name
jdbc.password=password
# 文件路徑配置
model.package=*.model.menu
mapper.package=*.mapper
xml.mapper.package=mapper.db
target.project=src/main
# 執行的表數據
table.name=SYS_MENU_T
table.domainObjectName=Menu
自定義插件文件:
GeneratorPlugin.java Model自定義注釋,Inteface 自定義基類,xml刪除多余方法 支持lombok插件

import org.apache.commons.lang3.StringUtils; import org.mybatis.generator.api.GeneratedXmlFile; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.api.dom.xml.Document; import org.mybatis.generator.api.dom.xml.Element; import java.util.Collection; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; /** * Mybatis 代碼生成自定義插件 * A MyBatis Generator plugin to use Lombok's annotations. * For example, use @Data annotation instead of getter ands setter. * * @className GeneratorPlugin * @author joe * @version V1.0.0 * @date 2019-01-16 */ public class GeneratorPlugin extends PluginAdapter { private final Collection<Annotations> annotations; /** * GeneratorPlugin constructor */ public GeneratorPlugin() { annotations = new LinkedHashSet<>(Annotations.values().length); } /** * @param warnings list of warnings * @return always true */ @Override public boolean validate(List<String> warnings) { return true; } /** * Intercepts base record class generation * * @param topLevelClass the generated base record class * @param introspectedTable The class containing information about the table as * introspected from the database * @return always true */ @Override public boolean modelBaseRecordClassGenerated( TopLevelClass topLevelClass, IntrospectedTable introspectedTable ) { addModelClassComment(topLevelClass, introspectedTable); return true; } /** * Intercepts primary key class generation * * @param topLevelClass the generated primary key class * @param introspectedTable The class containing information about the table as * introspected from the database * @return always true */ @Override public boolean modelPrimaryKeyClassGenerated( TopLevelClass topLevelClass, IntrospectedTable introspectedTable ) { addModelClassComment(topLevelClass, introspectedTable); return true; } /** * Intercepts "record with blob" class generation * * @param topLevelClass the generated record with BLOBs class * @param introspectedTable The class containing information about the table as * introspected from the database * @return always true */ @Override public boolean modelRecordWithBLOBsClassGenerated( TopLevelClass topLevelClass, IntrospectedTable introspectedTable ) { addModelClassComment(topLevelClass, introspectedTable); return true; } /** * 類屬性注釋 * * @param field 屬性 * @param topLevelClass 類對象 * @param introspectedColumn 列 * @param introspectedTable 表 * @param modelClassType Class類型 * @return true */ @Override public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { StringBuilder sb = new StringBuilder(); field.addJavaDocLine("/**"); sb.append(" * "); // 字段注釋 sb.append(columnRemarks(introspectedColumn.getRemarks())); field.addJavaDocLine(sb.toString().replace("\n", " ")); field.addJavaDocLine(" */"); // 主鍵 if (introspectedTable.getPrimaryKeyColumns().stream() .anyMatch(p -> p.equals(introspectedColumn))) { field.addAnnotation("@TableId"); } // 字段上生成@TableField注解 field.addAnnotation("@TableField(value = \"" + introspectedColumn.getActualColumnName() + "\")"); return true; } /** * Prevents all getters from being generated. * See SimpleModelGenerator * * @param method the getter, or accessor, method generated for the specified * column * @param topLevelClass the partially implemented model class * @param introspectedColumn The class containing information about the column related * to this field as introspected from the database * @param introspectedTable The class containing information about the table as * introspected from the database * @param modelClassType the type of class that the field is generated for */ @Override public boolean modelGetterMethodGenerated( Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType ) { return false; } /** * Prevents all setters from being generated * See SimpleModelGenerator * * @param method the setter, or mutator, method generated for the specified * column * @param topLevelClass the partially implemented model class * @param introspectedColumn The class containing information about the column related * to this field as introspected from the database * @param introspectedTable The class containing information about the table as * introspected from the database * @param modelClassType the type of class that the field is generated for * @return always false */ @Override public boolean modelSetterMethodGenerated( Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType ) { return false; } /** * 增加類注釋 * * @param topLevelClass 類 * @param introspectedTable 表數據 */ private void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { topLevelClass.addJavaDocLine("/**"); topLevelClass.addJavaDocLine(" * " + tableRemarks(introspectedTable)); topLevelClass.addJavaDocLine(" * "); topLevelClass.addJavaDocLine(" * @author " + System.getProperty("user.name")); topLevelClass.addJavaDocLine(" * @date " + new Date().toString()); topLevelClass.addJavaDocLine(" *"); topLevelClass.addJavaDocLine(" */"); addAnnotations(topLevelClass); topLevelClass.addImportedType("com.baomidou.mybatisplus.annotation.TableField"); topLevelClass.addImportedType("com.baomidou.mybatisplus.annotation.TableId"); topLevelClass.addImportedType("com.baomidou.mybatisplus.annotation.TableName"); // 添加類注解 // 表名 String tableName = introspectedTable.getFullyQualifiedTable().getIntrospectedTableName(); topLevelClass.addAnnotation(String.format("@TableName(\"%s\")", tableName)); } /** * Adds the lombok annotations' imports and annotations to the class * * @param topLevelClass the partially implemented model class */ private void addAnnotations(TopLevelClass topLevelClass) { //@Data is default annotation annotations.add(Annotations.DATA); annotations.add(Annotations.EQUALS); for (Annotations annotation : annotations) { topLevelClass.addImportedType(annotation.javaType); topLevelClass.addAnnotation(annotation.name); } } /** * 數據字典類型 mapper */ @Override public boolean clientGenerated( Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable ) { interfaze.addJavaDocLine("/**"); interfaze.addJavaDocLine(" * " + tableRemarks(introspectedTable) + " Mapper"); interfaze.addJavaDocLine(" * "); interfaze.addJavaDocLine(" * @author " + System.getProperty("user.name")); interfaze.addJavaDocLine(" * @date " + new Date().toString()); interfaze.addJavaDocLine(" *"); interfaze.addJavaDocLine(" */"); interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper")); interfaze.addAnnotation("@Mapper"); interfaze.addImportedType(new FullyQualifiedJavaType("com.baomidou.mybatisplus.core.mapper.BaseMapper")); FullyQualifiedJavaType superMapper = new FullyQualifiedJavaType(String.format("BaseMapper<%s>", introspectedTable.getBaseRecordType())); // 添加 extends MybatisPlusBaseMapper interfaze.addSuperInterface(superMapper); // 清理方法 interfaze.getMethods().clear(); return true; } @Override public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) { // 設置 xml文件時覆蓋寫 默認:true [mybatis generator默認采用追加方式生成] sqlMap.setMergeable(false); return super.sqlMapGenerated(sqlMap, introspectedTable); } @Override public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) { // 之前 table 配置 保留了 一個SelectByPrimaryKey 設置為true 此處刪除 List<Element> list = document.getRootElement().getElements(); list.remove(list.size() - 1); return true; } private String tableRemarks(IntrospectedTable introspectedTable) { String remark = introspectedTable.getRemarks(); if (StringUtils.isEmpty(remark)) { return introspectedTable.getFullyQualifiedTable().getIntrospectedTableName(); } return remark; } private String columnRemarks(String remark) { if (StringUtils.isEmpty(remark)) { return "TODO add remark"; } return remark; } /** * Lombok 相關的注解 * * @className Annotations * @author joe * @version V1.0.0 * @date 2019-02-21 10:35 */ private enum Annotations { /** * data */ DATA("data", "@Data", "lombok.Data"), BUILDER("builder", "@Builder", "lombok.Builder"), EQUALS("equalsAndHashCode", "@EqualsAndHashCode(callSuper = false)", "lombok.EqualsAndHashCode"), ALL_ARGS_CONSTRUCTOR("allArgsConstructor", "@AllArgsConstructor", "lombok.AllArgsConstructor"), NO_ARGS_CONSTRUCTOR("noArgsConstructor", "@NoArgsConstructor", "lombok.NoArgsConstructor"), ACCESSORS("accessors", "@Accessors", "lombok.experimental.Accessors"), TO_STRING("toString", "@ToString", "lombok.ToString"); private final String paramName; private final String name; private final FullyQualifiedJavaType javaType; Annotations(String paramName, String name, String className) { this.paramName = paramName; this.name = name; this.javaType = new FullyQualifiedJavaType(className); } } }
使用方式:
mvn mybatis-generator:generate
如果是在intellij 環境,直接鼠標點擊即可
生成效果:

import *.base.BaseModel; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; /** * 系統菜單 * * @author joe * @date 2019-01-20 * */ @Data @EqualsAndHashCode(callSuper = false) @TableName("SYS_MENU_T") public class Menu extends BaseModel { /** * 菜單ID */ @TableId @TableField(value = "MENU_ID") private String menuId; /** * 菜單編碼,不允許重復 */ @TableField(value = "MENU_CODE") private String menuCode; /** * 菜單名稱,同一個級別下不允許重復 */ @TableField(value = "MENU_NAME") private String menuName; }

import *.MenuEO; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * 系統菜單 Mapper * * @author joe * @date 2019-01-22 16:24 * */ @Mapper public interface MenuMapper extends BaseMapper<Menu> { }

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="*.mapper.MenuMapper">
<resultMap id="BaseResultMap" type="*.Menu">
<id column="MENU_ID" jdbcType="VARCHAR" property="menuId" />
<result column="MENU_CODE" jdbcType="VARCHAR" property="menuCode" />
<result column="MENU_NAME" jdbcType="VARCHAR" property="menuName" />
</resultMap>
<sql id="Base_Column_List">
MENU_ID, MENU_CODE, MENU_NAME
</sql>
</mapper>
常見問題:
1、運行報錯,找不到自定義的插件類[generate failed: Cannot instantiate object of type *.MyPlugin]
原因:mybatis-generator 的plugin有自己的classpath,我們在項目中直接繼承的類和plugin不屬於同一個classpath
解決:把插件類打基礎包,再pom的plugin配置中被 mybatis-generator 的plugin 依賴。
2、報錯[There are no statements enabled for table mybatis.category, this table will be ignored.]
原因:generatorConfig.xml中,<table>標簽配成 所有原始的sql都是false
解決:保留一個時true的設置,再插件中處理xml時再刪除。
3、獲取不到數據庫字段的注釋
原因:mysql 和 oracle的數據庫配置不同,確認配置
解決:在generatorConfiguration.xml配置文件中配置

<!--數據庫連接的信息:驅動類、連接地址、用戶名、密碼 --> <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"> <!-- 字段注解 針對oracle數據庫 --> <property name="remarksReporting" value="true" /> <!-- 字段注解 針對mysql數據庫 --> <property name="useInformationSchema" value="true"/> </jdbcConnection>
4、xml文件再次生成時被追加
原因:mybatis generator默認采用追加方式生成
解決:重寫sqlMapGenerated方法。設置sqlMap.setMergeable(false);。默認情況下isMergeable為true,所以在這里設置為false。
mybatis-generator.xml配置文件詳解 參考 https://blog.csdn.net/weixin_39805338/article/details/80999186