org.mybatis.generator.plugins.MapperConfigPlugin
在generatorConfig.xml中加上配置:
运行MBG,在resources下面生成了com.gen.mybatis包,并且正确添加了一个MapperConfig.xml(这个文件的名字是可以通过fileName参数来设置的,默认的文件名就是MapperConfig.xml),生成的文件如下:
这个插件的完成方式:
public class MapperConfigPlugin extends PluginAdapter {
......
}
该类仍然继承PluginAdapter;
private List mapperFiles;
public MapperConfigPlugin() {
mapperFiles = new ArrayList();
}
public boolean validate(List warnings) {
boolean valid = true;
//stringHasValue方法是通过静态引入工具类org.mybatis.generator.internal.util.StringUtility的;
//该方法用于判断传入的参数中是否含有targetProject这个参数;
//这里要注意两个点,第一,我们在扩展或者使用别人的框架的时候,比如stringHasValue这种方法,我们完全可以自己写一个hasLength方法,
//但是,使用框架中已经存在的API来完成这些功能,是一个扩展框架的一个良好的实践,这可以保证框架在API级别的一致性;
//第二,properties属性是Plugin在创建的时候,通过setProperties方法传入的,是一个Properties类型数据;
if (!stringHasValue(properties
.getProperty("targetProject"))) { //$NON-NLS-1$
//如果没有传入必填的参数,就把警告信息添加到传入的warnings列表中,该列表的内容会在MBG运行过程中统一日志;
//这里需要注意的是getString方法,该方法是通过静态引入org.mybatis.generator.internal.util.messages.Messages
//这个Messages类是MBG对国际化消息的一个封装,在后面扩展时候会讲到MBG的代码结构;
warnings.add(getString("ValidationError.18", //$NON-NLS-1$
"MapperConfigPlugin", //$NON-NLS-1$
"targetProject")); //$NON-NLS-1$
valid = false;
}
//同理,判断是否传入了targetPackage参数
if (!stringHasValue(properties
.getProperty("targetPackage"))) { //$NON-NLS-1$
warnings.add(getString("ValidationError.18", //$NON-NLS-1$
"MapperConfigPlugin", //$NON-NLS-1$
"targetPackage")); //$NON-NLS-1$
valid = false;
}
return valid;
}
因为这个插件需要传入参数,并且有两个必填参数,所以在validate方法中做了验证,通过这个方法,其实我们基本就能明白validate方法的作用了;
实现了contextGenerateAdditionalXmlFiles方法来为MBG添加额外需要生成的文件,看看这个方法:
public List contextGenerateAdditionalXmlFiles() {
//创建一个XML文档,注意这个Document不是JAVA DOM的,而是org.mybatis.generator.api.dom.xml.Document
//在这里传入了两个静态常量,这两个常量就是mybatis配置文件需要用到的DTD,
//在XmlConstants里面还有很多常量,比如MYBATIS3_MAPPER_SYSTEM_ID和MYBATIS3_MAPPER_PUBLIC_ID(看名字应该知道是什么内容吧~)
Document document = new Document(
XmlConstants.MYBATIS3_MAPPER_CONFIG_PUBLIC_ID,
XmlConstants.MYBATIS3_MAPPER_CONFIG_SYSTEM_ID);
//接着创建根目录,,和JavaDOM基本一样,就不啰嗦了;
XmlElement root = new XmlElement("configuration"); //$NON-NLS-1$
document.setRootElement(root);
//添加注释,这里做的有点不太规范,最好还是使用MBG提供的context.getCommentGenerator的addComment(XmlElement xmlElement)方法来统一生成注释
//可能作者想做更多的个性化的注释吧;
root.addElement(new TextElement("")); //$NON-NLS-1$
//创建mappers节点;
XmlElement mappers = new XmlElement("mappers"); //$NON-NLS-1$
root.addElement(mappers);
//准备根据搜集到的本次生成的mapper.xml文件,为mappers生成mapper子元素
XmlElement mapper;
//为每一个mapper.xml文件生成一个对应的mapper子元素;从这里就可以明确的看出,在mapperFiles集合中保存的确实是mapper.xml文件的路径;
for (String mapperFile : mapperFiles) {
mapper = new XmlElement("mapper"); //$NON-NLS-1$
mapper.addAttribute(new Attribute("resource", mapperFile)); //$NON-NLS-1$
mappers.addElement(mapper);
}
//信息量非常大的一句代码,通过这句代码可以看出:
//1,MBG使用GeneratedXmlFile对象来包装一个要生成的XML文件的所有相关内容;
//2,该对象的构造方法包含了所有需要的信息
//3,第一个参数,是该XML文件的内容,即Document;
//4,第二个参数,是该XML文件的文件名,可以很清楚的看到,先得到fileName参数,否则使用默认的MapperConfig.xml命名(所以,后缀名是要自己传给MBG的)
//5,第三个参数和第四个参数,分别是生成XML文件的targetPackage和targetProject;所以,可以看到MBG把文件的具体生成过程完全包装,只需要我们提供package和project即可;
//6,第四个参数代表是否合并,
//7,最后一个参数是提供一个XML文件格式化工具,直接使用上下文的xmlFormatter即可(这个是可以在元素中配置的哦~~)
GeneratedXmlFile gxf = new GeneratedXmlFile(document, properties
.getProperty("fileName", "MapperConfig.xml"), //$NON-NLS-1$ //$NON-NLS-2$
properties.getProperty("targetPackage"), //$NON-NLS-1$
properties.getProperty("targetProject"), //$NON-NLS-1$
false, context.getXmlFormatter());
//最后返回要生成的这个文件,交给MBG去生成;
List answer = new ArrayList(1);
answer.add(gxf);
return answer;
}
/**
* sqlMapGenerated方法,是在本次context中,生成每一个(注意是每一个)mapper.xml文件之后都会回调的方法;
* 第一个参数GeneratedXmlFile即本次生成的mapper.xml文件对应的XML文件封装对象;
*/
@Override
public boolean sqlMapGenerated(GeneratedXmlFile sqlMap,
IntrospectedTable introspectedTable) {
StringBuilder sb = new StringBuilder();
//得到目标package;
sb.append(sqlMap.getTargetPackage());
//添加一个.然后把所有的.替换成/,就变成了mapper.xml文件的目录(原来并没有方法直接得到,还是要自己通过package去替换)
sb.append('.');
String temp = sb.toString();
sb.setLength(0);
sb.append(temp.replace('.', '/'));
//接着拼上xml文件的文件名(还记得文件名是包含了后缀的吧),就创建好了这个mapper.xml文件的路径了
sb.append(sqlMap.getFileName());
//再添加到mapperFiles中
mapperFiles.add(sb.toString());
return true;
}