第一步:创建一个Maven项目:
- 添加依赖:
junit
junit
4.12
test
mysql
mysql-connector-java
8.0.11
org.mybatis
mybatis
3.4.6
org.mybatis.generator
mybatis-generator-core
1.3.7
- 在build标签下添加
org.mybatis.generator
mybatis-generator-maven-plugin
1.4.0
mysql
mysql-connector-java
8.0.11
${basedir}/src/main/resources/genCfg.xml
true
true
src/main/java
**/*.xml
第二步:在resources目录中创建属性文件mysql.properties:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1/test?useSSL=false&serverTimezone=CST
username=root
password=root
第三步:在resources目录下建立 genCfg.xml,作为mybatis-generator-maven-plugin 插件执行的配置文件:
说明:
-
用于加载配置项或者配置文件,在整个配置文件中就可以使用${propertyKey}的方式来引用配置项。它有以下两个属性:
- resource:配置资源加载地址,使用resource,MBG从classpath开始找,比如com/myproject/generatorConfig.properties
- url:配置资源加载地质,使用URL的方式,比如file:///C:/myfolder/generatorConfig.properties. 注意,两个属性只能选址一个; 另外,如果使用了mybatis-generator-maven-plugin,那么在pom.xml中定义的properties都可以直接在generatorConfig.xml中使用
-
:在MBG工作的时候,需要额外加载的依赖包。location属性指明加载jar/zip包的全路径
-
context:生成一组对象的环境
- id:必选,上下文id,用于在生成错误时提示
- defaultModelType:指定生成对象的样式 1,conditional:类似hierarchical; 2,flat:所有内容(主键,blob)等全部生成在一个对象中; 3,hierarchical:主键生成一个XXKey对象(key class),Blob等单独生成一个对象,其他简单属性在一个对象中(record class)
- targetRuntime: 1,MyBatis3:默认的值,生成基于MyBatis3.x以上版本的内容,包括XXXBySample; 2,MyBatis3Simple:类似MyBatis3,只是不生成XXXBySample;
- introspectedColumnImpl:类全限定名,用于扩展MBG
-
java类型处理器 javaTypeResolver,用于处理DB中的类型到Java中的类型,默认使用JavaTypeResolverDefaultImpl;先尝试使用Integer,Long,Short等来对应DECIMAL和 NUMERIC数据类型; 对于forceBigDecimals来说:
- true:使用BigDecimal对应DECIMAL和 NUMERIC数据类型
- false:默认, scale>0;length>18:使用BigDecimal; scale=0;length[10,18]:使用Long; scale=0;length[5,9]:使用Integer; scale=0;length
第四步:采用图形化的方式利用MBG产生代码 依次点击Maven Project—项目——Plugins——mybatis generator——Run Maven build,如下图所示:
改进 自定义代码生成器程序执行入口MBG采用图形化生成时会出现莫名其妙的问题,比如如果数据库中的表的名字为tb_admin时会会生成一堆莫名其妙的代码,所以建议通过程序生成代码而不是通过采用图形化的方式。在项目中按如下所示的代码创建程序执行入口类:
生成正确的代码注释public class MBGGenerator { public static void main( String[] args ) throws Exception { List warnings = new ArrayList(); String path = Generator.class.getResource("/").getPath(); File configFile = new File(path+"genCfg.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration cfg = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(true); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(cfg, callback, warnings); myBatisGenerator.generate(null); } }
查看生成代码中的实体类,发现尽管数据库中表及字段都有注释,但生成的实体类中出现了一大堆莫名其妙的英文信息。要想生成正确的代码注释: 第一步:按如下所示在com.hc.gen包下提供注释工具类
public class BeanCommentsGen implements CommentGenerator { private Properties properties; private Properties systemPro; private boolean suppressDate; private boolean suppressAllComments; private String currentDateStr; public BeanCommentsGen() { properties = new Properties(); } @Override public void addConfigurationProperties(Properties properties) { // 获取自定义的 properties this.properties.putAll(properties); } @Override public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { String author = properties.getProperty("author"); String dateFormat = properties.getProperty("dateFormat", "yyyy-MM-dd"); SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat); // 获取表注释 String remarks = introspectedTable.getRemarks(); topLevelClass.addJavaDocLine("/**"); topLevelClass.addJavaDocLine(" * " + remarks); topLevelClass.addJavaDocLine(" *"); topLevelClass.addJavaDocLine(" * @author " + author); topLevelClass.addJavaDocLine(" * @date " + dateFormatter.format(new Date())); topLevelClass.addJavaDocLine(" */"); } @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { // 获取列注释 String remarks = introspectedColumn.getRemarks(); field.addJavaDocLine("/**"); field.addJavaDocLine(" * " + remarks); field.addJavaDocLine(" */"); } @Override public void addFieldComment(Field field, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); field.addJavaDocLine("/**"); sb.append(" * "); sb.append(introspectedTable.getFullyQualifiedTable()); field.addJavaDocLine(sb.toString().replace("\n", " ")); field.addJavaDocLine(" */"); } @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) { if (suppressAllComments) { return; } StringBuilder sb = new StringBuilder(); innerClass.addJavaDocLine("/**"); sb.append(" * "); sb.append(introspectedTable.getFullyQualifiedTable()); innerClass.addJavaDocLine(sb.toString()); sb.setLength(0); sb.append(" * @author "); sb.append(systemPro.getProperty("user.name")); sb.append(" "); sb.append(currentDateStr); // addJavadocTag(innerClass, markAsDoNotDelete); innerClass.addJavaDocLine(" */"); } @Override public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) { } @Override public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) { } @Override public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (suppressAllComments) { return; } method.addJavaDocLine("/**"); StringBuilder sb = new StringBuilder(); sb.append(" * 获取"); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); sb.setLength(0); sb.append(" * @return "); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); // addJavadocTag(method, false); method.addJavaDocLine(" */"); } @Override public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { if (suppressAllComments) { return; } method.addJavaDocLine("/**"); StringBuilder sb = new StringBuilder(); sb.append(" * 设置"); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); Parameter parm = method.getParameters().get(0); sb.setLength(0); sb.append(" * @param "); sb.append(parm.getName()); sb.append(" "); sb.append(introspectedColumn.getRemarks()); method.addJavaDocLine(sb.toString()); // addJavadocTag(method, false); method.addJavaDocLine(" */"); } @Override public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) { } @Override public void addJavaFileComment(CompilationUnit compilationUnit) { } @Override public void addComment(XmlElement xmlElement) { } @Override public void addRootComment(XmlElement rootElement) { } @Override public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable, Set imports) { } @Override public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set imports) { } @Override public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, Set imports) { } @Override public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn, Set imports) { } @Override public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable, Set imports) { } }
第二步:将genCfg文件中编号③处的代码替换成如下所示的内容:
第三步:运行MBGGenerator 程序,发现在项目中生成了实体类、DAO接口以及映射文件的代码,如下图所示:
生成正确的Mapper文件查看发现生成的DAO接口以及映射文件中没有注释了,最重要的是实体类的注释符合也我们要求了
自定义生成正确的代码注释后,又发现Mapper文件中的代码出错了,生成了两次。我们采用如下步骤解决这个问题: 第一步:按如下所示在com.hc.gen包下编写代码:
public class OverIsMergeablePlugin extends PluginAdapter { @Override public boolean validate(List warnings) { return true; } @Override public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable it) { try { Field field = sqlMap.getClass().getDeclaredField("isMergeable"); field.setAccessible(true); field.setBoolean(sqlMap, false); } catch (Exception e) { e.printStackTrace(); } return true; } }
第二步:在genCfg.xml文件中代码②处添加如下代码:
再次运行MBGGenerator类的main方法发现生成的DAO接口以及映射文件中和实体类都符合也我们要求了。
生成带Lombok注解的Bean第一步:继承Mybatis的插件适配器,自定义插件,代码如下:
public class MyBatisLombokPlugin extends PluginAdapter { @Override public boolean validate(List list) { return true; } @Override public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { //添加domain的import topLevelClass.addImportedType("lombok.Getter"); topLevelClass.addImportedType("lombok.Setter"); topLevelClass.addImportedType("lombok.Builder"); topLevelClass.addImportedType("lombok.NoArgsConstructor"); topLevelClass.addImportedType("lombok.AllArgsConstructor"); topLevelClass.addImportedType("lombok.ToString"); //添加domain的注解 topLevelClass.addAnnotation("@Getter"); topLevelClass.addAnnotation("@Setter"); topLevelClass.addAnnotation("@Builder"); topLevelClass.addAnnotation("@NoArgsConstructor"); topLevelClass.addAnnotation("@AllArgsConstructor"); topLevelClass.addAnnotation("@ToString(callSuper = true)"); return true; } @Override public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) { //Mapper文件的注释 return true; } @Override public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { //不生成getter return false; } @Override public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) { //不生成setter return false; } }
第二步:在MBG配置文件genCfg.xml中添加如下代码
同时不再需要以下三行配置
再次运行MBGGenerator类的main方法发现使用Lombok生成实体类了。
附件:完整的MBG配置文件