mybatis代码生成+自定义注解+自定义注释实例
目录
- mybatis代码生成
- 配置文件
- 配置类
- 自定义的lombok注解配置
- 代码注释配置
mybatis代码生成
<!--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
<?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://localhost:3306/project1?useUnicode=true&useSSL=false&characterEncoding=utf8" userId="test" password="123456"/> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!--todo entity包路径--> <javaModelGenerator targetPackage="com.cc.learn.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="com.cc.learn.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="User" 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>
配置类
自定义的lombok注解配置
效果:
在类上添加注解
@Data @AllArgsConstructor @NoArgsConstructor @Builder public class User { }
在时间字段上自动添加注解
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date endTime;
代码
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(); } } }
代码注释配置
代码生成时,使用数据控的注释给字段添加文档注释
效果
/** * 编号 */ private String planId;
代码
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(" */"); } }
调用
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(); } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。
【转自:荷兰服务器 】