XMLMapperBuilder でSQLMapper XML を parse

去年、以下を書いたけれど、、
XMLMapperBuilder を使ってみる。 - Oboe吹きプログラマの黙示録
Java インターフェースクラスで書く Mapper の指定になってしまっている。
クラスローダーが読み込める全ての classpath から、XMLを見つけて parse する方法として書いてみる。

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.session.Configuration;
/**
 * ConfigurationTool
 */
public class ConfigurationTool{

    public int mapperScan(Configuration config) {
        return findXML().stream().mapToInt(f->{
            try(InputStream input = new FileInputStream(f)){
                new XMLMapperBuilder(input, config, f.getAbsolutePath(), config.getSqlFragments()).parse();
                return 1;
            }catch(Exception e){
                return 0;
            }
        }).sum();
    }
   public List<File> findXML(){
        File file = new File(Thread.currentThread().getContextClassLoader().getResource("./").getPath());
        return searchMapFiles(file, new ArrayList<>(), f->f.getName().endsWith(".xml"));
    }
    private List<File> searchMapFiles(File file, List<File> list, Predicate<File> p){
        if (p.test(file)) list.add(file);
        if (file.isDirectory()){
            for(File f:file.listFiles()){
                searchMapFiles(f, list, p);
            }
        }
        return list;
    }
}

使用例

UnpooledDataSource dataSource = new UnpooledDataSource();
dataSource.setDriver("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/testDB");
dataSource.setUsername("root");
dataSource.setPassword("passwd");

Environment environment = new Environment("deployment", new JdbcTransactionFactory(), dataSource);
Configuration config = new Configuration(environment);
// snake Case → camel Case
config.setMapUnderscoreToCamelCase(true);

ConfigurationTool tool = new ConfigurationTool();
int count = tool.mapperScan(config);

これで、Configuration config は、読込める全てのSQL Map XMLを解析する。
int count には、読み込んだXMLファイル数が返ってくる。
どんな MapperStatement が認識されたかは、Configuration を調べればよい。

// mapper 識別子 ID と mapper のリソースを確認
config.getMappedStatements().stream().forEach(m->{
    System.out.println("id="+m.getId() +"   "+m.getResource());
});

// mapper レジストリに格納された mapper Java インターフェースクラス名を確認
config.getMapperRegistry().getMappers().forEach(c->{
    System.out.println(c.getName());
});

上の m.getResource() は、
mapper Java インターフェースクラスによるものであれば、
     ~.java (best guess)
XML に記述されたものであれば、
     XMLファイルパス (末尾文字列が、".xml" )
のString である。

だから、SQLMap XML だけのリストをここから作るには、、

List<File> files = config.getMappedStatements().stream()
                 .map(m->m.getResource().toString())
                 .filter(e->e.endsWith(".xml"))
                 .distinct().map(p->new File(p))
                 .collect(Collectors.toList());

で、File の List を作れる。