Mybatis中Generator代码生成工具 实例解析

本文详细解析MyBatis Generator的工作原理,包括如何使用Generator生成实体类、映射接口及配置文件,以及如何通过自定义插件扩展其功能,如批量插入和批量更新。同时介绍了如何通过扩展生成器添加进度回调,以监控生成过程。

1.当前项目使用的Mybatis框架,如果新建表则 需要使用到Mybatis的 Generator工具 生成相关代码(dao接口 xml配置文件 entity实体类),之前只知道怎么用,借着现在这个机会 研究下Generator这个工具怎么用的.Mybatis中的Generator官网地址如在这里插入图片描述http://www.mybatis.org/generator/index.html.

3.Mybatis中存在多种运行Generator的方式,这里采用最通用的java方式.具体示例代码如下 这里扩展了Generator的生成器,添加了ProgressCallback长时间进程回调,需要在扩展生成器MyGenerator中的generate方法 调用该ProgressCallback接口实例,具体在官网中也有讲到.

GenMybatis 生成器

package com.bxd.core.util;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.ProgressCallback;
import org.mybatis.generator.api.VerboseProgressCallback;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import com.bxd.core.support.MyGenerator;

public class GenMybatis {

	public static void main(String[] args) {
		List<String> warnings = new ArrayList<String>();
		boolean overwrite = true;
		String filePath = ClassLoader.getSystemResource("config/generatorConfig.xml").getPath();
		System.out.println(filePath);
		
		File configFile = new File(filePath);
		Configuration config;
		try {
			
			ConfigurationParser cp = new ConfigurationParser(warnings);

			config = cp.parseConfiguration(configFile);
			

			DefaultShellCallback shellCallback = new DefaultShellCallback(overwrite);

			MyGenerator myBatisGenerator = new MyGenerator(config, shellCallback, warnings);

			ProgressCallback progressCallback = new VerboseProgressCallback();//扩展mybatis生成器,实现长时间线程回调通知,重写generate方法

			myBatisGenerator.generate(progressCallback);
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
		} 
      

    }
		

}

MyGenerator 扩展生成器类

package com.bxd.core.support;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.ProgressCallback;
import org.mybatis.generator.api.ShellCallback;
import org.mybatis.generator.codegen.RootClassInfo;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.config.MergeConstants;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.ShellException;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.mybatis.generator.internal.NullProgressCallback;
import org.mybatis.generator.internal.ObjectFactory;
import org.mybatis.generator.internal.XmlFileMergerJaxp;
import org.mybatis.generator.internal.util.ClassloaderUtility;
import org.mybatis.generator.internal.util.messages.Messages;


public class MyGenerator {
	 /** The configuration. */
    private Configuration configuration;

    /** The shell callback. */
    private ShellCallback shellCallback;

    /** The generated java files. */
    private List<GeneratedJavaFile> generatedJavaFiles;

    /** The generated xml files. */
    private List<GeneratedXmlFile> generatedXmlFiles;

    /** The warnings. */
    private List<String> warnings;

    /** The projects. */
    private Set<String> projects;

    /**
     * Constructs a MyBatisGenerator object.
     * 
     * @param configuration
     *            The configuration for this invocation
     * @param shellCallback
     *            an instance of a ShellCallback interface. You may specify
     *            <code>null</code> in which case the DefaultShellCallback will
     *            be used.
     * @param warnings
     *            Any warnings generated during execution will be added to this
     *            list. Warnings do not affect the running of the tool, but they
     *            may affect the results. A typical warning is an unsupported
     *            data type. In that case, the column will be ignored and
     *            generation will continue. You may specify <code>null</code> if
     *            you do not want warnings returned.
     * @throws InvalidConfigurationException
     *             if the specified configuration is invalid
     */
    public MyGenerator(Configuration configuration, ShellCallback shellCallback,
            List<String> warnings) throws InvalidConfigurationException {
        super();
        if (configuration == null) {
            throw new IllegalArgumentException(Messages.getString("RuntimeError.2")); //$NON-NLS-1$
        } else {
            this.configuration = configuration;
        }

        if (shellCallback == null) {
            this.shellCallback = new DefaultShellCallback(false);
        } else {
            this.shellCallback = shellCallback;
        }

        if (warnings == null) {
            this.warnings = new ArrayList<String>();
        } else {
            this.warnings = warnings;
        }
        generatedJavaFiles = new ArrayList<GeneratedJavaFile>();
        generatedXmlFiles = new ArrayList<GeneratedXmlFile>();
        projects = new HashSet<String>();

        this.configuration.validate();
    }

    /**
     * This is the main method for generating code. This method is long running, but progress can be provided and the
     * method can be canceled through the ProgressCallback interface. This version of the method runs all configured
     * contexts.
     *
     * @param callback
     *            an instance of the ProgressCallback interface, or <code>null</code> if you do not require progress
     *            information
     * @throws SQLException
     *             the SQL exception
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     * @throws InterruptedException
     *             if the method is canceled through the ProgressCallback
     */
    public void generate(ProgressCallback callback) throws SQLException,
            IOException, InterruptedException {
        generate(callback, null, null, true);
    }

    /**
     * This is the main method for generating code. This method is long running, but progress can be provided and the
     * method can be canceled through the ProgressCallback interface.
     *
     * @param callback
     *            an instance of the ProgressCallback interface, or <code>null</code> if you do not require progress
     *            information
     * @param contextIds
     *            a set of Strings containing context ids to run. Only the contexts with an id specified in this list
     *            will be run. If the list is null or empty, than all contexts are run.
     * @throws SQLException
     *             the SQL exception
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     * @throws InterruptedException
     *             if the method is canceled through the ProgressCallback
     */
    public void generate(ProgressCallback callback, Set<String> contextIds)
            throws SQLException, IOException, InterruptedException {
        generate(callback, contextIds, null, true);
    }

    /**
     * This is the main method for generating code. This method is long running, but progress can be provided and the
     * method can be cancelled through the ProgressCallback interface.
     *
     * @param callback
     *            an instance of the ProgressCallback interface, or <code>null</code> if you do not require progress
     *            information
     * @param contextIds
     *            a set of Strings containing context ids to run. Only the contexts with an id specified in this list
     *            will be run. If the list is null or empty, than all contexts are run.
     * @param fullyQualifiedTableNames
     *            a set of table names to generate. The elements of the set must be Strings that exactly match what's
     *            specified in the configuration. For example, if table name = "foo" and schema = "bar", then the fully
     *            qualified table name is "foo.bar". If the Set is null or empty, then all tables in the configuration
     *            will be used for code generation.
     * @throws SQLException
     *             the SQL exception
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     * @throws InterruptedException
     *             if the method is canceled through the ProgressCallback
     */
    public void generate(ProgressCallback callback, Set<String> contextIds,
            Set<String> fullyQualifiedTableNames) throws SQLException,
            IOException, InterruptedException {
        generate(callback, contextIds, fullyQualifiedTableNames, true);
    }

    /**
     * This is the main method for generating code. This method is long running, but progress can be provided and the
     * method can be cancelled through the ProgressCallback interface.
     *
     * @param callback
     *            an instance of the ProgressCallback interface, or <code>null</code> if you do not require progress
     *            information
     * @param contextIds
     *            a set of Strings containing context ids to run. Only the contexts with an id specified in this list
     *            will be run. If the list is null or empty, than all contexts are run.
     * @param fullyQualifiedTableNames
     *            a set of table names to generate. The elements of the set must be Strings that exactly match what's
     *            specified in the configuration. For example, if table name = "foo" and schema = "bar", then the fully
     *            qualified table name is "foo.bar". If the Set is null or empty, then all tables in the configuration
     *            will be used for code generation.
     * @param writeFiles
     *            if true, then the generated files will be written to disk.  If false,
     *            then the generator runs but nothing is written
     * @throws SQLException
     *             the SQL exception
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     * @throws InterruptedException
     *             if the method is canceled through the ProgressCallback
     */
    public void generate(ProgressCallback callback, Set<String> contextIds,
            Set<String> fullyQualifiedTableNames, boolean writeFiles) throws SQLException,
            IOException, InterruptedException {

        if (callback == null) {
            callback = new NullProgressCallback();
        }

        generatedJavaFiles.clear();
        generatedXmlFiles.clear();
        ObjectFactory.reset();
        RootClassInfo.reset();

        // calculate the contexts to run
        List<Context> contextsToRun;
        if (contextIds == null || contextIds.size() == 0) {
            contextsToRun = configuration.getContexts();
        } else {
            contextsToRun = new ArrayList<Context>();
            for (Context context : configuration.getContexts()) {
                if (contextIds.contains(context.getId())) {
                    contextsToRun.add(context);
                }
            }
        }

        // setup custom classloader if required
        if (configuration.getClassPathEntries().size() > 0) {
            ClassLoader classLoader = ClassloaderUtility.getCustomClassloader(configuration.getClassPathEntries());
            ObjectFactory.addExternalClassLoader(classLoader);
        }

        // now run the introspections...
        int totalSteps = 0;
        for (Context context : contextsToRun) {
            totalSteps += context.getIntrospectionSteps();
        }
        callback.introspectionStarted(totalSteps);

        for (Context context : contextsToRun) {
            context.introspectTables(callback, warnings,
                    fullyQualifiedTableNames);
        }

        // now run the generates
        totalSteps = 0;
        for (Context context : contextsToRun) {
            totalSteps += context.getGenerationSteps();
        }
        callback.generationStarted(totalSteps);

        for (Context context : contextsToRun) {
            context.generateFiles(callback, generatedJavaFiles,
                    generatedXmlFiles, warnings);
        }

        // now save the files
        if (writeFiles) {
            callback.saveStarted(generatedXmlFiles.size()
                + generatedJavaFiles.size());

            for (GeneratedXmlFile gxf : generatedXmlFiles) {
                projects.add(gxf.getTargetProject());
                writeGeneratedXmlFile(gxf, callback);
            }

            for (GeneratedJavaFile gjf : generatedJavaFiles) {
                projects.add(gjf.getTargetProject());
                writeGeneratedJavaFile(gjf, callback);
            }

            for (String project : projects) {
                shellCallback.refreshProject(project);
            }
        }

        callback.done();
    }

    private void writeGeneratedJavaFile(GeneratedJavaFile gjf, ProgressCallback callback)
            throws InterruptedException, IOException {
        File targetFile;
        String source;
        try {
            File directory = shellCallback.getDirectory(gjf
                    .getTargetProject(), gjf.getTargetPackage());
            targetFile = new File(directory, gjf.getFileName());
            if (targetFile.exists()) {
                if (shellCallback.isMergeSupported()) {
                	source = this.shellCallback.mergeJavaFile(gjf.getFormattedContent(), targetFile.getAbsolutePath(),
							MergeConstants.OLD_ELEMENT_TAGS, gjf.getFileEncoding());
                } else if (shellCallback.isOverwriteEnabled()) {
                    source = gjf.getFormattedContent();
                    warnings.add(Messages.getString("Warning.11", //$NON-NLS-1$
                            targetFile.getAbsolutePath()));
                } else {
                    source = gjf.getFormattedContent();
                    targetFile = getUniqueFileName(directory, gjf
                            .getFileName());
                    warnings.add(Messages.getString(
                            "Warning.2", targetFile.getAbsolutePath())); //$NON-NLS-1$
                }
            } else {
                source = gjf.getFormattedContent();
            }

            callback.checkCancel();
            callback.startTask(Messages.getString(
                    "Progress.15", targetFile.getName())); //$NON-NLS-1$
            writeFile(targetFile, source, gjf.getFileEncoding());
        } catch (ShellException e) {
            warnings.add(e.getMessage());
        }
    }

    private void writeGeneratedXmlFile(GeneratedXmlFile gxf, ProgressCallback callback)
            throws InterruptedException, IOException {
        File targetFile;
        String source;
        try {
            File directory = shellCallback.getDirectory(gxf
                    .getTargetProject(), gxf.getTargetPackage());
            targetFile = new File(directory, gxf.getFileName());
            if (targetFile.exists()) {
            	boolean merge = false;
                if (merge) {
                    source = XmlFileMergerJaxp.getMergedSource(gxf,
                            targetFile);
                } else if (shellCallback.isOverwriteEnabled()) {
                    source = gxf.getFormattedContent();
                    warnings.add(Messages.getString("Warning.11", //$NON-NLS-1$
                            targetFile.getAbsolutePath()));
                } else {
                    source = gxf.getFormattedContent();
                    targetFile = getUniqueFileName(directory, gxf
                            .getFileName());
                    warnings.add(Messages.getString(
                            "Warning.2", targetFile.getAbsolutePath())); //$NON-NLS-1$
                }
            } else {
                source = gxf.getFormattedContent();
            }

            callback.checkCancel();
            callback.startTask(Messages.getString(
                    "Progress.15", targetFile.getName())); //$NON-NLS-1$
            writeFile(targetFile, source, "UTF-8"); //$NON-NLS-1$
        } catch (ShellException e) {
            warnings.add(e.getMessage());
        }
    }
    
    /**
     * Writes, or overwrites, the contents of the specified file.
     *
     * @param file
     *            the file
     * @param content
     *            the content
     * @param fileEncoding
     *            the file encoding
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    private void writeFile(File file, String content, String fileEncoding) throws IOException {
        FileOutputStream fos = new FileOutputStream(file, false);
        OutputStreamWriter osw;
        if (fileEncoding == null) {
            osw = new OutputStreamWriter(fos);
        } else {
            osw = new OutputStreamWriter(fos, fileEncoding);
        }
        
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write(content);
        bw.close();
    }

    /**
     * Gets the unique file name.
     *
     * @param directory
     *            the directory
     * @param fileName
     *            the file name
     * @return the unique file name
     */
    private File getUniqueFileName(File directory, String fileName) {
        File answer = null;

        // try up to 1000 times to generate a unique file name
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < 1000; i++) {
            sb.setLength(0);
            sb.append(fileName);
            sb.append('.');
            sb.append(i);

            File testFile = new File(directory, sb.toString());
            if (!testFile.exists()) {
                answer = testFile;
                break;
            }
        }

        if (answer == null) {
            throw new RuntimeException(Messages.getString(
                    "RuntimeError.3", directory.getAbsolutePath())); //$NON-NLS-1$
        }

        return answer;
    }

    /**
     * Returns the list of generated Java files after a call to one of the generate methods.
     * This is useful if you prefer to process the generated files yourself and do not want
     * the generator to write them to disk.
     *  
     * @return the list of generated Java files
     */
    public List<GeneratedJavaFile> getGeneratedJavaFiles() {
        return generatedJavaFiles;
    }

    /**
     * Returns the list of generated XML files after a call to one of the generate methods.
     * This is useful if you prefer to process the generated files yourself and do not want
     * the generator to write them to disk.
     *  
     * @return the list of generated XML files
     */
    public List<GeneratedXmlFile> getGeneratedXmlFiles() {
        return generatedXmlFiles;
}
}

在这里插入图片描述
在这里插入图片描述
3.运行Generator类 需要相关的generatorConfig.xml配置文件,主要是javaModelGenerator实体类生成位置,sqlMapGenerator实体类映射配置文件位置,javaClientGenerator 映射接口文件位置,jdbc加载相关驱动,自定义插件(如批量更新,批量删除功能等).生成哪张表的代码

<?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>

	<!--<classPathEntry location="D:/ftworkspace/hmzxface/WebContent/WEB-INF/lib/ojdbc6.jar" />-->
	<classPathEntry location="WebContent/WEB-INF/lib/mysql-connector-java-5.1.34.jar" />	
	<context id="MySqlTables" targetRuntime="MyBatis3">
				
	    <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>
        
        <!-- 生成的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"/>
			
          
         <!--自定义批量插入--> 
        <plugin type="com.bxd.core.plugin.BatchInsertPlugin"></plugin> 
        
        <!--自定义批量更新--> 
        <plugin type="com.bxd.core.plugin.BatchUpdatePlugin"></plugin>
        
        <plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>          
		
		<!--  suppressAllComments  生成代码默认添加注释false,此处修改为true,不添加备注
		        suppressDate  默认添加时间栈到生成代码中false,此处修改为true,不添加备注
		-->
		<commentGenerator>
			<property name="suppressAllComments" value="true" />
			<property name="suppressDate" value="true" />
		</commentGenerator>
		
		
		<!-- 本地数据库 连接位置 -->
		<!-- ORACLE -->
        <!--<jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" 
						connectionURL="jdbc:oracle:thin:@localhost:1521:orcl" 
						userId="root" password="123456">
        </jdbcConnection>-->
		<!-- MYSQL -->
		<jdbcConnection driverClass="com.mysql.jdbc.Driver" 
			connectionURL="jdbc:mysql://localhost:3306/pv_web2"
		userId="root" password="1234"/>
		
		<!-- 不强制使用BigDecimal,可以的话使用short Integer ,为了更方便的处理  false 代表不强制使用-->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>
		
		
		<!--  实体类配置文件生成路径 -->
		<javaModelGenerator targetPackage="com.bxd.app.entity" targetProject="src">
			<property name="enableSubPackages" value="true" />
			<property name="trimStrings" value="true" />
		</javaModelGenerator>
		
		<!-- mapping xml配置文件生成位置-->
		<sqlMapGenerator targetPackage="mapping" targetProject="resources">
			<property name="enableSubPackages" value="true" />
		</sqlMapGenerator>
	
	    <!-- mapper映射接口位置  -->
		<javaClientGenerator type="XMLMAPPER" targetPackage="com.bxd.app.mapper" targetProject="src">
			<property name="enableSubPackages" value="true" />
		</javaClientGenerator>	
		
		<!-- 自动生成目标表  可以使用bd_%   通配符-->
		<table tableName="biz_project_survey">
		   
		</table>	
		<!--table tableName="T_RES_LOG">		   
		</table>
		<table tableName="TMP_RES_LOG">		   
		</table-->
		
		
		
		
		
		
	
		<!--enableInsert ="true" enableCountByExample="true" enableUpdateByExample="true" enableDeleteByExample="true" enableSelectByExample="true" selectByExampleQueryId="true" -->
	</context>
</generatorConfiguration>

在这里插入图片描述
在这里插入图片描述

4.上面配置文件中提到的 BatchInsertPlugin批量插入,BatchUpdatePlugin批量更新插件属于自定义的,而SerializablePlugin是属于Mybatis提供的拆件(作用是实现序列化接口).其中自定义插件需要继承PluginAdapter插件扩展适配器类.主要是重写生成model实体类,xml配置文件,映射接口的方法.具体代码如下
在这里插入图片描述
在这里插入图片描述
BatchInsertPlugin

package com.bxd.core.plugin;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.OutputUtilities;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;

public class BatchInsertPlugin extends PluginAdapter {
	
	public BatchInsertPlugin() {
		super();
	}

	public boolean validate(List<String> paramList) {
		return true;
	}
	

	public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable) {
		generateBatchInsert(interfaze, introspectedTable);
		return super.clientGenerated(interfaze, topLevelClass, introspectedTable);
	}

	public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
		
		String tableName = introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime();//数据库表名  
		
		List<IntrospectedColumn> columns = new ArrayList<IntrospectedColumn>();	
		
		XmlElement parentElement = document.getRootElement();

		XmlElement batchInsertElement = new XmlElement("insert");
		batchInsertElement.addAttribute(new Attribute("id", "batchInsert"));
		batchInsertElement.addAttribute(new Attribute("parameterType", "list"));
		
		StringBuilder sql = new StringBuilder("insert into "+ tableName +"\n");
		OutputUtilities.xmlIndent(sql, 3);
		sql.append("(");
		StringBuilder cols = new StringBuilder("");
		StringBuilder vals = new StringBuilder("");
		columns = introspectedTable.getAllColumns();
		
		Iterator<IntrospectedColumn> iterator = columns.iterator();
		int i = 0;
		//OutputUtilities.xmlIndent(cols,3);
		//OutputUtilities.xmlIndent(vals, 3);
		while(iterator.hasNext()){
			IntrospectedColumn column = iterator.next();	
			cols.append(column.getActualColumnName()).append(",");	
			vals.append("#{ item."+column.getJavaProperty()+", jdbcType="+column.getJdbcTypeName()+"}");
			vals.append(",");
			i++;
			if(i==3){				
				cols.append("\n");
				vals.append("\n");
				OutputUtilities.xmlIndent(cols,3);
				OutputUtilities.xmlIndent(vals, 3);
				i=0;
			}		
			
		}
		cols = cols.deleteCharAt(cols.lastIndexOf(","));
		vals = vals.deleteCharAt(vals.lastIndexOf(","));
		sql.append(cols.toString()).append(")\n");
		OutputUtilities.xmlIndent(sql,2);
		sql.append("values \n");
		OutputUtilities.xmlIndent(sql,2);
		sql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" separator=\",\" > \n");
		OutputUtilities.xmlIndent(sql,3);
		sql.append("( "+vals.toString()+") \n");
		
		OutputUtilities.xmlIndent(sql,2);
		sql.append("</foreach>");
		
		batchInsertElement.addElement(
				new TextElement(
						sql.toString()
				));
		
		parentElement.addElement(batchInsertElement);


		return super.sqlMapDocumentGenerated(document, introspectedTable);
	}

	/**
	 * 自定义批量插入方法
	 * @param interfaze
	 * @param introspectedTable
	 */
	private void generateBatchInsert(Interface interfaze,IntrospectedTable introspectedTable) {
		
		Method m = new Method("batchInsert");
		
		m.setVisibility(JavaVisibility.PUBLIC);
		
		m.setReturnType(FullyQualifiedJavaType.getIntInstance());
		
		String type = "";
		if(!introspectedTable.getRules().generatePrimaryKeyClass()){
			type = introspectedTable.getBaseRecordType();
		}
		else{
			type = introspectedTable.getPrimaryKeyType();
		}
				
		m.addParameter(new Parameter(new FullyQualifiedJavaType("List<"+type+">"), "list"));

		context.getCommentGenerator().addGeneralMethodComment(m,
				introspectedTable);
		
		interfaze.addImportedType(FullyQualifiedJavaType.getNewListInstance());
		interfaze.addImportedType(new FullyQualifiedJavaType(type));
		interfaze.addMethod(m);
	}


}


BatchUpdatePlugin

package com.bxd.core.plugin;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.OutputUtilities;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;

public class BatchUpdatePlugin extends PluginAdapter {

	public BatchUpdatePlugin(){
		super();
	}
	
	public boolean validate(List<String> paramList) {
		return true;
	}

	public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable) {
		
		if(!introspectedTable.getNonPrimaryKeyColumns().isEmpty()){
			generateBatchUpdate(interfaze, introspectedTable);
		}
	
		return super.clientGenerated(interfaze, topLevelClass, introspectedTable);
	}

	public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
		
		String tableName = introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime();//数据库表名  
		
		List<IntrospectedColumn> columns = new ArrayList<IntrospectedColumn>();	
		
		List<IntrospectedColumn> primeKeys = new ArrayList<IntrospectedColumn>();
		
		XmlElement parentElement = document.getRootElement();		
		
		columns = introspectedTable.getNonPrimaryKeyColumns();
		primeKeys = introspectedTable.getPrimaryKeyColumns();
		
		if(!columns.isEmpty()){
			XmlElement batchUpdateElement = new XmlElement("update");
			batchUpdateElement.addAttribute(new Attribute("id", "batchUpdate"));
			batchUpdateElement.addAttribute(new Attribute("parameterType", "list"));
			
			StringBuilder sql = new StringBuilder("");
			sql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" separator=\";\" > \n");
			OutputUtilities.xmlIndent(sql, 3);
			sql.append("update " + tableName+" \n");
			OutputUtilities.xmlIndent(sql, 3);
			sql.append("<set>\n");
			
			StringBuilder sets = new StringBuilder("");
			StringBuilder keys = new StringBuilder("");
			
			Iterator<IntrospectedColumn> iterator = columns.iterator();
			while(iterator.hasNext()){
				IntrospectedColumn column = iterator.next();	
				OutputUtilities.xmlIndent(sets, 4);
				sets.append("<if test=\"item." + column.getJavaProperty() + " != null\"> \n");
				OutputUtilities.xmlIndent(sets, 5);
				sets.append(column.getActualColumnName() + " = #{item."+column.getJavaProperty()+", "
						+ "jdbcType = "+column.getJdbcTypeName()+"},\n");
				OutputUtilities.xmlIndent(sets, 4);
				sets.append("</if> \n");
			}
			OutputUtilities.xmlIndent(sets, 3);
			sets.append("</set>"+"\n");
			
			Iterator<IntrospectedColumn> key = primeKeys.iterator();
			OutputUtilities.xmlIndent(keys, 3);
			keys.append("<where>"+"\n");
			while(key.hasNext()){
				IntrospectedColumn keycol = key.next();	
				OutputUtilities.xmlIndent(keys, 4);
				keys.append("<if test=\"item." + keycol.getJavaProperty() + " != null\">\n");
				OutputUtilities.xmlIndent(keys, 5);
				keys.append(" and " +keycol.getActualColumnName() + " = #{item."+keycol.getJavaProperty()+","
						+ "jdbcType = "+keycol.getJdbcTypeName()+"}\n");
				OutputUtilities.xmlIndent(keys, 4);
				keys.append("</if>\n");
			}
			OutputUtilities.xmlIndent(keys, 3);
			keys.append("</where>"+"\n");
			sql.append(sets.toString());
			sql.append(keys.toString());
			OutputUtilities.xmlIndent(sql, 2);		
			sql.append("</foreach>");
				
			
			batchUpdateElement.addElement(
					new TextElement(
							sql.toString()
					));
			
			parentElement.addElement(batchUpdateElement);
			
		}

		return super.sqlMapDocumentGenerated(document, introspectedTable);
	}

	/**
	 * 自定义批量插入方法
	 * @param interfaze
	 * @param introspectedTable
	 */
	private void generateBatchUpdate(Interface interfaze,IntrospectedTable introspectedTable) {
		
		Method m = new Method("batchUpdate");
		
		m.setVisibility(JavaVisibility.PUBLIC);
		
		m.setReturnType(FullyQualifiedJavaType.getIntInstance());
		
		String type = "";
		if(!introspectedTable.getRules().generatePrimaryKeyClass()){
			type = introspectedTable.getBaseRecordType();
		}
		else{
			type = introspectedTable.getPrimaryKeyType();
		}
				
		m.addParameter(new Parameter(new FullyQualifiedJavaType("List<"+type+">"), "list"));

		context.getCommentGenerator().addGeneralMethodComment(m,
				introspectedTable);
		
		interfaze.addImportedType(FullyQualifiedJavaType.getNewListInstance());
		interfaze.addImportedType(new FullyQualifiedJavaType(type));
		interfaze.addMethod(m);
	}

	
	
}

最后总结起来:Mybatis中的generator主要是在新增或者修改表结构的时候,初始化相关的简单CURD所需要的实体类,映射接口,映射接口配置文件.同时根据实际项目需求 添加自定义批量修改,插入组件或Mybatis提供的序列化插件,完成一些机械性代码的自动初始化.配合上重写的generator生成器 添加上需要的ProgressCallback进程进度回调类,扩展generator生成器.最后加上开源的PageHelper分页查询帮助类(需要添加到mybatis.xml配置文件中),帮助提高开发效率.

所以mybatis的generator=generator.xml+Generator运行文件+MyGenerator(扩展生成器 添加ProcessCallBack进度回调)+自定义插件(BatchInsert批量插入+BatchUpdate批量更新)+Mybatis提供的序列化拆件=完成的初始化表相关curd的功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值