最近有个需要获取ibatis xml配置文件里的resultmap映射信息,主要是解析出有哪些column和对应的property及class。配置文件大家都知道的:类似如下:
<sqlMap namespace="xxx-xxx">
<typeAlias alias="xxx-PRIVILEGE" type="xxx.PrivilegeDO"/>
<resultMap class="xxx-PRIVILEGE" id="xxx-PRIVILEGE">
<result property="id"column="id" jdbcType="NUMBERIC"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="title" column="title" jdbcType="VARCHAR"/>
<result property="description" column="description" jdbcType="VARCHAR"/>
<result property="link" column="link" jdbcType="VARCHAR"/>
<result property="gmtCreate" column="gmt_create" jdbcType="TIMESTAMP"/>
<result property="gmtModified" column="gmt_modified" jdbcType="TIMESTAMP"/>
</resultMap>
想了两个方案,一:直接自己解析xml文件。但由于只能在运行时才处理这些信息,如果预先收集别人的sqlmap配置文件显得不靠谱,且很可能要搜索很多相关jar包。
二:可否通过ibatis自身的解析过程来获取到。于是查了下源码和debug跟踪,发现resultmap是可以拿到的。最开始的思路是通过SqlMapClientImpl获取Mappedstatement来返回resultmap,通过反射用这个resultmap的父类获取delegate后就可以获取到相关的映射信息了,delegate在resultmap父类里是私有的,所以需要反射把该field的accessible设为true。代码如下:
public void getResutMap() throws IOException {
String resource = "giza-sqlmap.xml";
Reader reader;
reader = Resources.getResourceAsReader(resource);
// XmlSqlMapClientBuilder xmlBuilder = new XmlSqlMapClientBuilder();
// SqlMapClientBuilder sqlMap = xmlBuilder.buildSqlMap(reader);
// sqlMap.buildSqlMapClient(reader)
// public List<UserInfo> getUserList(UserInfo userInfo) {
// String sql = null;
SqlMapClient client = SqlMapClientBuilder.buildSqlMapClient(reader);
SqlMapClientImpl sqlmap = (SqlMapClientImpl) client;
MappedStatement stmt = sqlmap
.getMappedStatement("MS-COUNT-FOR-GROWTH-MEMBER-DEGRADED");
ResultMap resultmap = stmt.getResultMap();
Class<?> resultmapType = resultmap.getClass();
Field field;
try {
field = resultmapType.getSuperclass().getDeclaredField("delegate");
field.setAccessible(true);
SqlMapExecutorDelegate delegate=(SqlMapExecutorDelegate) field.get(resultmap);
System.out.println(delegate);
ResultMap resultmaps=delegate.getResultMap(delegate.getResultMapNames().next().toString());
System.out.println(resultmaps.getResultClass());
ResultMapping mappings[]=resultmaps.getResultMappings();
for(int i=0;i<mappings.length;i++){
BasicResultMapping mapping=(BasicResultMapping) mappings[i];
System.out.println("propertyname="+mapping.getPropertyName());
System.out.println("columname="+mapping.getColumnName());
}
field.setAccessible(false);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println(resultmap...getResultMappings());
// Sql stmtSql = stmt.getSql();
// stmtSql.get
// RequestScope requestScope = new RequestScope();
// requestScope.setStatement(stmt);
// sql = stmtSql.getSql(requestScope, userInfo);
// System.out.println(sql);
// return null;
}
大功告成。。写完后回过头看下悲催的发现其实SqlMapClientImpl可以直接获取delegate...害我浪费了这么多时间还反射来获取,只怪没把源码看仔细啊。于时改成下面OK,剩下的自己再封装下吧:
public void getResutMap() throws IOException {
String resource = "giza-sqlmap.xml";
Reader reader;
reader = Resources.getResourceAsReader(resource);
SqlMapClient client = SqlMapClientBuilder.buildSqlMapClient(reader);
SqlMapClientImpl sqlmap = (SqlMapClientImpl) client;
SqlMapExecutorDelegate delegate=sqlmap.delegate;
System.out.println(delegate);
ResultMap resultmaps=delegate.getResultMap(delegate.getResultMapNames().next().toString());
System.out.println(resultmaps.getResultClass());
ResultMapping mappings[]=resultmaps.getResultMappings();
for(int i=0;i<mappings.length;i++){
BasicResultMapping mapping=(BasicResultMapping) mappings[i];
System.out.println("propertyname="+mapping.getPropertyName());
System.out.println("columname="+mapping.getColumnName());
}
}