资料:
文档:http://www.mybatis.org/generator/configreference/table.html
下载:https://github.com/mybatis/generator
快速开始:
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
源码分析:
1. MyBatisGenerator 构造器:没有做特别的事情,主要就是初始化并校验配置文件。
super();
if (configuration == null) {
throw new IllegalArgumentException(getString("RuntimeError.2"));
} 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();
generatedXmlFiles = new ArrayList();
projects = new HashSet<String>();
this.configuration.validate();
if (callback == null) {
callback = new NullProgressCallback();
}
generatedJavaFiles.clear();
generatedXmlFiles.clear();
ObjectFactory.reset();
RootClassInfo.reset();
// 1.从配置文件中获取到上下文信息。对应配置文件的标签,几乎所有的配置都在这个标签之内。
List contextsToRun;
if (contextIds == null || contextIds.size() == 0) {
contextsToRun = configuration.getContexts();
} else {
contextsToRun = new ArrayList();
for (Context context : configuration.getContexts()) {
if (contextIds.contains(context.getId())) {
contextsToRun.add(context);
}
}
}
// 2.加载自定义的class文件,主要用于加载数据库驱动。
if (configuration.getClassPathEntries().size() > 0) {
ClassLoader classLoader = getCustomClassloader(configuration.getClassPathEntries());
ObjectFactory.addExternalClassLoader(classLoader);
}
// 3.统计处理步骤,并调用callback对应的方法。
int totalSteps = 0;
for (Context context : contextsToRun) {
totalSteps += context.getIntrospectionSteps();
}
callback.introspectionStarted(totalSteps);
// 4.开始处理表信息,这里是生成代码的实际处理的第一步。
for (Context context : contextsToRun) {
context.introspectTables(callback, warnings,
fullyQualifiedTableNames);
}
// 5.类似于第3步,通常情况下没有什么用处。
totalSteps = 0;
for (Context context : contextsToRun) {
totalSteps += context.getGenerationSteps();
}
callback.generationStarted(totalSteps);
// 6.开始生成文件,这一步是生成实际的文件。
for (Context context : contextsToRun) {
context.generateFiles(callback, generatedJavaFiles,
generatedXmlFiles, warnings);
}
// 7.将文件写到本地。
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();
a) 处理表信息:Context. introspectTables 方法 Context 的构造器的逻辑也没有特别的,只是简单的初始化。
introspectedTables = new ArrayList();
// 1.创建类型处理器,主要用于处理数据库数据类型与java类型的对应关系
JavaTypeResolver javaTypeResolver = ObjectFactory
.createJavaTypeResolver(this, warnings);
Connection connection = null;
try {
callback.startTask(getString("Progress.0"));
connection = getConnection();
//2.构造出数据库信息类来,这个构造器只是初始化了一些变量。
DatabaseIntrospector databaseIntrospector = new DatabaseIntrospector(
this, connection.getMetaData(), javaTypeResolver, warnings);
for (TableConfiguration tc : tableConfigurations) {
String tableName = composeFullyQualifiedTableName(tc.getCatalog(), tc
.getSchema(), tc.getTableName(), '.');
if (fullyQualifiedTableNames != null
&& fullyQualifiedTableNames.size() > 0
&& !fullyQualifiedTableNames.contains(tableName)) {
continue;
}
if (!tc.areAnyStatementsEnabled()) {
warnings.add(getString("Warning.0", tableName));
continue;
}
callback.startTask(getString("Progress.1", tableName));
// 3.根据配置创建出IntrospectedTable类,此时已经将数据库栏位名称对应的字段名以及数据库数据类型对应的java类型都已经计算出来了。
List tables = databaseIntrospector
.introspectTables(tc);
if (tables != null) {
introspectedTables.addAll(tables);
}
callback.checkCancel();
}
} finally {
closeConnection(connection);
}
b) 生成文件:Context.generateFiles
pluginAggregator = new PluginAggregator();
// 1.处理插件信息.暂时先忽略
for (PluginConfiguration pluginConfiguration : pluginConfigurations) {
Plugin plugin = ObjectFactory.createPlugin(this,
pluginConfiguration);
if (plugin.validate(warnings)) {
pluginAggregator.addPlugin(plugin);
} else {
warnings.add(getString("Warning.24", //$NON-NLS-1$
pluginConfiguration.getConfigurationType(), id));
}
}
if (introspectedTables != null) {
for (IntrospectedTable introspectedTable : introspectedTables) {
callback.checkCancel();
//2.初始化相关属性.
introspectedTable.initialize();
//3.计算出需要使用的生成器.
introspectedTable.calculateGenerators(warnings, callback);
generatedJavaFiles.addAll(introspectedTable
.getGeneratedJavaFiles());
generatedXmlFiles.addAll(introspectedTable
.getGeneratedXmlFiles());
generatedJavaFiles.addAll(pluginAggregator
.contextGenerateAdditionalJavaFiles(introspectedTable));
generatedXmlFiles.addAll(pluginAggregator
.contextGenerateAdditionalXmlFiles(introspectedTable));
}
}
generatedJavaFiles.addAll(pluginAggregator
.contextGenerateAdditionalJavaFiles());
generatedXmlFiles.addAll(pluginAggregator
.contextGenerateAdditionalXmlFiles());
c) 写入到本地文件中:调用GeneratedJavaFile的getFormattedContent方法获得java文件内容;调用GeneratedXmlFile的getFormattedContent方法获得xml文件的内容。