MyBatisは優れた永続層フレームワークであり、カスタムSQL、ストアドプロシージャ、高度なマッピングをサポートしています。JDBCコードのほとんどすべてと手動パラメータ設定、結果取得を回避し、XMLまたはアノテーションで設定を管理します。
XML設定ファイルの例:
SqlSessionFactoryの構築プロセスではXML設定の解析が行われます:
設定解析の主要メソッド:
セッション開始時のトランザクション処理:
クエリ実行時の処理フロー:
キャッシュキーの生成ロジック:
クエリ実行とキャッシュの相互作用:
データベースからの直接取得処理:
@Slf4j
public class MyBatisExample {
@Test
public void verifyCache() throws IOException {
String configPath = "mybatis-config.xml";
InputStream configStream = Resources.getResourceAsStream(configPath);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(configStream);
SqlSession session = sessionFactory.openSession();
session.selectOne("com.example.mapper.UserMapper.retrieveUser", 3);
}
}<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<typeAliases>
<typeAlias type="com.example.model.User" alias="user"/>
</typeAliases>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db"/>
<property name="username" value="user"/>
<property name="password" value="pass"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapping/UserMapper.xml"/>
</mappers>
</configuration><?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="com.example.mapper.UserMapper">
<select id="retrieveUser" parameterType="int" resultType="user">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>public SqlSessionFactory build(InputStream input, String env, Properties props) {
XMLConfigBuilder parser = new XMLConfigBuilder(input, env, props);
return this.build(parser.parse());
}public Configuration parse() {
parseConfiguration(parser.evalNode("/configuration"));
return this.configuration;
}
private void parseConfiguration(XNode root) {
propertiesElement(root.evalNode("properties"));
typeAliasesElement(root.evalNode("typeAliases"));
environmentsElement(root.evalNode("environments"));
mapperElement(root.evalNode("mappers"));
}private SqlSession openSessionFromDataSource() {
Environment env = configuration.getEnvironment();
TransactionFactory txFactory = getTransactionFactory(env);
Transaction tx = txFactory.newTransaction(env.getDataSource(), null, false);
Executor executor = configuration.newExecutor(tx, ExecutorType.SIMPLE);
return new DefaultSqlSession(configuration, executor, false);
}public <T> T selectOne(String statementId, Object param) {
List<T> results = selectList(statementId, param);
if (results.size() == 1) return results.get(0);
if (results.size() > 1) throw new TooManyResultsException();
return null;
}public CacheKey createCacheKey(MappedStatement ms, Object param, BoundSql boundSql) {
CacheKey key = new CacheKey();
key.update(ms.getId());
key.update(boundSql.getSql());
for (ParameterMapping mapping : boundSql.getParameterMappings()) {
String prop = mapping.getProperty();
Object value = getParameterValue(prop, param, boundSql);
key.update(value);
}
return key;
}public <E> List<E> query(MappedStatement ms, Object param, CacheKey key, BoundSql boundSql) {
if (cache != null) {
List<E> cached = (List<E>) tcm.getObject(cache, key);
if (cached != null) return cached;
List<E> fresh = delegate.query(ms, param, key, boundSql);
tcm.putObject(cache, key, fresh);
return fresh;
}
return delegate.query(ms, param, key, boundSql);
}private <E> List<E> queryFromDatabase(MappedStatement ms, Object param, CacheKey key, BoundSql boundSql) {
localCache.putObject(key, EXECUTION_PLACEHOLDER);
List<E> results = doQuery(ms, param, boundSql);
localCache.putObject(key, results);
return results;
}