<!--mybatis的包和反向生成的包__用來生成dao,entity層--> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.4</version> </dependency> <!-- mybatis-generator-core 反向生成java代碼--> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.5</version> </dependency>
在resources
文件夾中建立文件mbgConfiguration.xml
java
<?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"> <!-- 第一種mybatis逆向生成xml配置 --> <generatorConfiguration> <context id="sqlserverTables" targetRuntime="MyBatis3" defaultModelType="flat"> <!-- 自動識別數據庫關鍵字,默認false,若是設置爲true,根據SqlReservedWords中定義的關鍵字列表; 通常保留默認值,遇到數據庫關鍵字(Java關鍵字),使用columnOverride覆蓋 --> <!--<property name="autoDelimitKeywords" value="false"/>--> <!-- 生成的Java文件的編碼 --> <property name="javaFileEncoding" value="UTF-8"/> <!-- 格式化java代碼 --> <property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/> <!-- 格式化XML代碼 --> <property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/> <!-- beginningDelimiter和endingDelimiter:指明數據庫的用於標記數據庫對象名的符號,好比ORACLE就是雙引號,MYSQL默認是`反引號; --> <property name="beginningDelimiter" value="`"/> <property name="endingDelimiter" value="`"/> <!-- 使用自定義的插件:entity的lombok註解 --> <plugin type="net.cc.gen.utils.LombokPlugin"/> <!--todo 文件名替換--> <!-- 此處是將Example更名爲Criteria 固然 想改爲什麼都行~ --> <plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin"> <property name="searchString" value="Example$" /> <!-- 替換後 <property name="replaceString" value="Criteria" /> --> <property name="replaceString" value="Query" /> </plugin> <!-- 此處是將UserMapper.xml更名爲UserDao.xml 固然 想改爲什麼都行~ --> <!--<plugin type="org.mybatis.generator.plugins.rename.RenameSqlMapperPlugin">--> <!--<property name="searchString" value="Mapper" />--> <!--<property name="replaceString" value="Dao" />--> <!--</plugin>--> <!-- 此處是將UserMapper更名爲UserDao 接口 固然 想改爲什麼都行~ --> <!--<plugin type="org.mybatis.generator.plugins.rename.RenameJavaMapperPlugin">--> <!--<property name="searchString" value="Mapper$" />--> <!--<property name="replaceString" value="Dao" />--> <!--</plugin>--> <!-- 經過type指定自定義的註釋 --> <commentGenerator type="net.cc.gen.utils.MyCommentGenerator"/> <!--todo 數據庫連接URL、用戶名、密碼 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://192.168.3.37:3306/UCareDB_Test?useUnicode=true&useSSL=false&characterEncoding=utf8" userId="test" password="123456"/> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!--todo entity包路徑--> <javaModelGenerator targetPackage="net.cc.ucare.entity" targetProject="src/main/java"> <!-- 在targetPackage的基礎上,根據數據庫的schema再生成一層package,最終生成的類放在這個package下,默認爲false --> <property name="enableSubPackages" value="true"/> <!-- 從數據庫返回的值被清理先後的空格,對String類型字段調用trim()方法 --> <property name="trimStrings" value="true"/> </javaModelGenerator> <!--todo mapper的xml路徑--> <sqlMapGenerator targetPackage="mappings" targetProject="src/main/resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!--todo mapper的java文件路徑--> <javaClientGenerator type="XMLMAPPER" targetPackage="net.cc.ucare.dao.mysql.mapper" targetProject="src/main/java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!--todo tableName須要生成的table名字 useActualColumnNames 駝峯命名 字段類型爲text格式的字段須要專門配置 <columnOverride column="AIRSPACE_DATA" javaType="java.lang.String" jdbcType="VARCHAR"/> <columnOverride column="AIRSPACES_DESC" javaType="java.lang.String" jdbcType="VARCHAR"/> --> <table tableName="FLY_PLAN_AVIATION_INFO" schema="crmii" delimitIdentifiers="true"><property name="useActualColumnNames" value="false"/></table> <!--<table tableName="數據表2" schema="crmii" delimitIdentifiers="true"><property name="useActualColumnNames" value="false"/></table>--> <!--<table tableName="數據表3" schema="crmii" delimitIdentifiers="true"><property name="useActualColumnNames" value="false"/></table>--> </context> </generatorConfiguration>
效果:mysql
在類上添加註解 @Data @AllArgsConstructor @NoArgsConstructor @Builder public class FlyPlanAviationInfo { } 在時間字段上自動添加註解 @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date endTime;
代碼spring
import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.Plugin; import org.mybatis.generator.api.PluginAdapter; import org.mybatis.generator.api.dom.java.*; import java.util.*; /** 自定義的lombok註解配置 * @author jingshiyu * @date 2019/9/17 12:04:47 * @desc */ public class LombokPlugin extends PluginAdapter { private final Collection<Annotations> annotations; /** * LombokPlugin constructor */ public LombokPlugin() { 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) { addAnnotations(topLevelClass); 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) { addAnnotations(topLevelClass); 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) { addAnnotations(topLevelClass); return true; } /** * 設置get set方法(使用lombok不須要,直接返回false) */ @Override public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { return false; } /** * 設置set方法 */ @Override public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { return false; } /** * 設置lombok註解 <br> */ private void addAnnotations(TopLevelClass topLevelClass) { for (Annotations annotation : annotations) { topLevelClass.addImportedType(annotation.javaType); topLevelClass.addAnnotation(annotation.asAnnotation()); } } /** * entity類設置 * @param properties */ @Override public void setProperties(Properties properties) { super.setProperties(properties); //@Data is default annotation annotations.add(Annotations.DATA); annotations.add(Annotations.ALL_ARGS_CONSTRUCTOR); annotations.add(Annotations.NO_ARGS_CONSTRUCTOR); annotations.add(Annotations.BUILDER); for (String annotationName : properties.stringPropertyNames()) { if (annotationName.contains(".")) { continue; } String value = properties.getProperty(annotationName); if (!Boolean.parseBoolean(value)) { // The annotation is disabled, skip it continue; } Annotations annotation = Annotations.getValueOf(annotationName); if (annotation == null) { continue; } String optionsPrefix = annotationName + "."; for (String propertyName : properties.stringPropertyNames()) { if (!propertyName.startsWith(optionsPrefix)) { // A property not related to this annotation continue; } String propertyValue = properties.getProperty(propertyName); annotation.appendOptions(propertyName, propertyValue); annotations.add(annotation); annotations.addAll(Annotations.getDependencies(annotation)); } } } /** * mapper類設置註解 */ @Override public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper")); interfaze.addAnnotation("@Mapper"); return true; } /** * entity字段設置 */ @Override public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, Plugin.ModelClassType modelClassType) { if (field.getType().getShortNameWithoutTypeArguments().equals("Date")) { field.getAnnotations().add(Annotations.DATE_TIME_FORMAT.asAnnotation()); field.getAnnotations().add(Annotations.JSON_FORMAT.asAnnotation()); topLevelClass.addImportedType(Annotations.DATE_TIME_FORMAT.javaType); topLevelClass.addImportedType(Annotations.JSON_FORMAT.javaType); } return true; } private enum Annotations { DATA("data", "@Data", "lombok.Data"), BUILDER("builder", "@Builder", "lombok.Builder"), 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"), DATE_TIME_FORMAT("dateTimeFormat", "@DateTimeFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")", "org.springframework.format.annotation.DateTimeFormat"), JSON_FORMAT("jsonFormat", "@JsonFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")", "com.fasterxml.jackson.annotation.JsonFormat"); private final String paramName; private final String name; private final FullyQualifiedJavaType javaType; private final List<String> options; Annotations(String paramName, String name, String className) { this.paramName = paramName; this.name = name; this.javaType = new FullyQualifiedJavaType(className); this.options = new ArrayList<String>(); } private static Annotations getValueOf(String paramName) { for (Annotations annotation : Annotations.values()) { if (String.CASE_INSENSITIVE_ORDER.compare(paramName, annotation.paramName) == 0) { return annotation; } } return null; } private static Collection<Annotations> getDependencies(Annotations annotation) { if (annotation == ALL_ARGS_CONSTRUCTOR) { return Collections.singleton(NO_ARGS_CONSTRUCTOR); } else { return Collections.emptyList(); } } // A trivial quoting. // Because Lombok annotation options type is almost String or boolean. private static String quote(String value) { if (Boolean.TRUE.toString().equals(value) || Boolean.FALSE.toString().equals(value)) // case of boolean, not passed as an array. { return value; } return value.replaceAll("[\\w]+", "\"$0\""); } private void appendOptions(String key, String value) { String keyPart = key.substring(key.indexOf(".") + 1); String valuePart = value.contains(",") ? String.format("{%s}", value) : value; this.options.add(String.format("%s=%s", keyPart, quote(valuePart))); } private String asAnnotation() { if (options.isEmpty()) { return name; } StringBuilder sb = new StringBuilder(); sb.append(name); sb.append("("); boolean first = true; for (String option : options) { if (first) { first = false; } else { sb.append(", "); } sb.append(option); } sb.append(")"); return sb.toString(); } } }
代碼生成時,使用數據控的註釋給字段添加文檔註釋sql
效果數據庫
/** * 編號 */ private String planId;
代碼apache
import com.baomidou.mybatisplus.core.toolkit.StringUtils; import org.mybatis.generator.api.CommentGenerator; import org.mybatis.generator.api.IntrospectedColumn; import org.mybatis.generator.api.IntrospectedTable; import org.mybatis.generator.api.dom.java.*; import org.mybatis.generator.api.dom.xml.XmlElement; import org.mybatis.generator.config.MergeConstants; import org.mybatis.generator.config.PropertyRegistry; import org.mybatis.generator.internal.util.StringUtility; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Properties; import static org.mybatis.generator.internal.util.StringUtility.isTrue; /** * mybatis逆向工程默認的註釋修改(使用表的註釋) * * @author jingshiyu * @date 2019/7/17 17:39:36 * @desc */ public class MyCommentGenerator implements CommentGenerator { /** * The properties. */ private Properties properties; /** * The suppress date. */ private boolean suppressDate; /** * The suppress all comments. */ private boolean suppressAllComments; /** * 是否添加doc註釋,true:不添加,false:添加<br> * The addition of table remark's comments. * If suppressAllComments is true, this option is ignored */ private boolean addRemarkComments; private SimpleDateFormat dateFormat; public MyCommentGenerator() { super(); properties = new Properties(); suppressDate = false; suppressAllComments = false; addRemarkComments = false; } @Override public void addJavaFileComment(CompilationUnit compilationUnit) { } /** * 實體類對應的mapper.xml註釋,mapper類不加註釋,若有須要參考 DefaultCommentGenerator */ @Override public void addComment(XmlElement xmlElement) { if (suppressAllComments) { return; } } @Override public void addRootComment(XmlElement rootElement) { } @Override public void addConfigurationProperties(Properties properties) { this.properties.putAll(properties); suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE)); suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS)); addRemarkComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_ADD_REMARK_COMMENTS)); String dateFormatString = properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_DATE_FORMAT); if (StringUtility.stringHasValue(dateFormatString)) { dateFormat = new SimpleDateFormat(dateFormatString); } } protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) { javaElement.addJavaDocLine(" *"); StringBuilder sb = new StringBuilder(); sb.append(" * "); sb.append(MergeConstants.NEW_ELEMENT_TAG); if (markAsDoNotDelete) { sb.append(" do_not_delete_during_merge"); } String s = getDateString(); if (s != null) { sb.append(' '); sb.append(s); } javaElement.addJavaDocLine(sb.toString()); } protected String getDateString() { if (suppressDate) { return null; } else if (dateFormat != null) { return dateFormat.format(new Date()); } else { return new Date().toString(); } } /** * 設置class的註解 */ @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); innerClass.addJavaDocLine("/**"); // sb.append(" * This class corresponds to the database table "); sb.append(introspectedTable.getFullyQualifiedTable()); innerClass.addJavaDocLine(sb.toString()); addJavadocTag(innerClass, false); innerClass.addJavaDocLine(" */"); } /** * 方法註釋 */ @Override public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { if (suppressAllComments || !addRemarkComments) { return; } StringBuilder sb = new StringBuilder(); topLevelClass.addJavaDocLine("/**"); //設置數據庫的備註 String remarks = introspectedTable.getRemarks(); if (addRemarkComments && StringUtility.stringHasValue(remarks)) { topLevelClass.addJavaDocLine(" * Database Table Remarks:"); String[] remarkLines = remarks.split(System.getProperty("line.separator")); for (String remarkLine : remarkLines) { topLevelClass.addJavaDocLine(" * " + remarkLine); } } topLevelClass.addJavaDocLine(" *"); sb.append(introspectedTable.getFullyQualifiedTable()); topLevelClass.addJavaDocLine(sb.toString()); addJavadocTag(topLevelClass, true); topLevelClass.addJavaDocLine(" */"); } /** * 添加枚舉的註釋 */ @Override public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); innerEnum.addJavaDocLine("/**"); sb.append(introspectedTable.getFullyQualifiedTable()); innerEnum.addJavaDocLine(sb.toString()); addJavadocTag(innerEnum, false); innerEnum.addJavaDocLine(" */"); } /** * 實體類字段註釋 */ @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (suppressAllComments || StringUtils.isEmpty(introspectedColumn.getRemarks())) { return; } field.addJavaDocLine("/**"); StringBuilder sb = new StringBuilder(); // introspectedColumn.getRemarks() 就是獲取字段註釋 sb.append(" * " + introspectedColumn.getRemarks()); field.addJavaDocLine(sb.toString()); field.addJavaDocLine(" */"); } /** * 實體類的靜態字段 */ @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } } /** * 實體類toString方法 */ @Override public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } } /** * 實體類getter方法註釋 */ @Override public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (suppressAllComments) { return; } } /** * 實體類setter註釋 */ @Override public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (suppressAllComments) { return; } } /** * 類註釋 * @param innerClass * @param introspectedTable * @param markAsDoNotDelete */ @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); innerClass.addJavaDocLine("/**"); sb.append(introspectedTable.getFullyQualifiedTable()); innerClass.addJavaDocLine(sb.toString()); addJavadocTag(innerClass, markAsDoNotDelete); innerClass.addJavaDocLine(" */"); } }
調用json
import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.exception.InvalidConfigurationException; import org.mybatis.generator.internal.DefaultShellCallback; import java.io.File; import java.util.ArrayList; import java.util.List; /** * java代碼生成器(會生成example的entity)<br> * mybatis逆向工程 * * @author jingshiyu * @date 2019/7/17 17:24 * @desc java代碼生成器(會生成example的entity)<br> */ public class JavaExampleGenerator { public static void main(String[] args) { List<String> warnings = new ArrayList<String>(); boolean overwrite = true; //若是這裏出現空指針,直接寫絕對路徑便可。 String genCfg = "/mbgConfiguration.xml"; File configFile = new File(JavaExampleGenerator.class.getResource(genCfg).getFile()); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = null; try { config = cp.parseConfiguration(configFile); } catch (Exception e) { e.printStackTrace(); } DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = null; try { myBatisGenerator = new MyBatisGenerator(config, callback, warnings); } catch (InvalidConfigurationException e) { e.printStackTrace(); } try { myBatisGenerator.generate(null); } catch (Exception e) { e.printStackTrace(); } } }