在最近的项目中,用到了MyIbatis3的动态加载映射文件的XML功能。在运行时动态添加SqlMapper映射文件。在网上没有查到相关资料,所以就自己研究了一下MyIbatis的Spring组件中的org.mybatis.spring.SqlSessionFactoryBean,研究其生成SqlSessionFactory过程,在buildSqlSessionFactory方法的末尾找到了加载映射文件的过程,代码如下:
if (!isEmpty(this.mapperLocations)) {
for (Resource mapperLocation : this.mapperLocations) {
if (mapperLocation == null) {
continue;
}
try {
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
configuration, mapperLocation.toString(), configuration.getSqlFragments());
xmlMapperBuilder.parse();
} catch (Exception e) {
throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Parsed mapper file: '" + mapperLocation + "'");
}
}
} else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Property 'mapperLocations' was not specified or no matching resources found");
}
}
return this.sqlSessionFactoryBuilder.build(configuration);
可以看出主要加载的是configuration,只要获得了configuration,就可以动态加载了,SqlSessionFactory对象可以通过ApplicationContext上下文获得。
通过文件加载XML示例代码如下:
public static void loadXml(File file, SqlSessionFactory sqlSessionFactory) {
Configuration configuration = sqlSessionFactory.getConfiguration();
if (file.exists()) {
try {
new XMLMapperBuilder(new FileInputStream(file), configuration,
file.toURI().toString(),
configuration.getSqlFragments()).parse();
} catch (Throwable e) {
}
}
}
如果如Spring接口,就可以使用Spring的Resource对象来实现多次载入,可在Bean中配置的对象实现ApplicationContextAware接口,获取ApplicationContext对象的引用,从而使用通配符来加载多个XML文件,示例代码如下:
public static void loadXml(String locations,
SqlSessionFactory sqlSessionFactory,
ApplicationContext applicationContext) {
if (locations == null)
return;
String[] mapperLocations = locations.split(",");
Configuration configuration = sqlSessionFactory.getConfiguration();
for (String location : mapperLocations) {
try {
Resource[] resources = applicationContext
.getResources(location);
if (resources != null) {
for (Resource resource : resources) {
new XMLMapperBuilder(resource.getInputStream(),
configuration, resource.toString(),
configuration.getSqlFragments()).parse();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}