mybatis与数据库会话的步骤如下
1、通过SqlSessionFactoryBuilder类的build来创建SqlSessionFactory;
2、通过SqlSessionFactory来打开sqlsession会话;
3、通过sqlsession来执行数据库sql;
4、关闭sqlsession会话。
从SqlSessionFactoryBuilder类中看到build的很多重载方法最终调用的是如下方法,也就是返回的是mybatis自己实现的DefaultSqlSessionFactory类的实例。
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
DefaultSqlSessionFactory的opensession方法最终调用如下方法,主要是创建执行器Executor,返回DefaultSqlSession实例。
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
Executor executor = this.configuration.newExecutor(tx, execType);
return new DefaultSqlSession(this.configuration, executor);
} catch (Exception e) {
closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
try {
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
Transaction tx = transactionFactory.newTransaction(connection);
Executor executor = this.configuration.newExecutor(tx, execType);
return new DefaultSqlSession(this.configuration, executor);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
DefaultSqlSession中的selectOne最终执行的就是selectList,而insert和delete方法最终执行的也是update方法。
public T selectOne(String statement) {
return selectOne(statement, null);
}
public T selectOne(String statement, Object parameter)
{
List list = selectList(statement, parameter);
if (list.size() == 1)
return list.get(0);
if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
}
return null;
}
public int insert(String statement) {
return insert(statement, null);
}
public int insert(String statement, Object parameter) {
return update(statement, parameter);
}
public int update(String statement, Object parameter) {
try {
this.dirty = true;
MappedStatement ms = this.configuration.getMappedStatement(statement);
return this.executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
public int update(String statement) { return update(statement, null); }
selectList和update方法都是通过Configuration来MappedStatement对象,获取绑定的相关sql信息,然后使用Executor来执行相关sql。
public List selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = this.configuration.getMappedStatement(statement);
List result = this.executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
return result;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
public int update(String statement, Object parameter) {
try {
this.dirty = true;
MappedStatement ms = this.configuration.getMappedStatement(statement);
return this.executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
以simpleExecutor为例,通过Configuration来创建StatementHandler,通过该对象来创建Statement对象来操作数据库。
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}
public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException
{
Connection connection = getConnection(statementLog);
Statement stmt = handler.prepare(connection);
handler.parameterize(stmt);
return stmt;
}
另外mybatis还可以通过mapper接口的代理来完成操作
通过DefaultSession中的getMapper获得mapper的代理类
public T getMapper(Class type) {
return this.configuration.getMapper(type, this);
}
public T getMapper(Class type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
再看MapperRegistry的getMapper方法,通过MapperProxy来创建mapper的代理类
public T getMapper(Class type, SqlSession sqlSession) {
if (!this.knownMappers.contains(type))
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
try {
return MapperProxy.newMapperProxy(type, sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
再看MapperProxy这个类,通过Proxy来创建代理类,MapperProxy实现了InvocationHandler接口,那么我们知道调用原接口的方法时,会转而调用MapperProxy的invoke方法。
public static T newMapperProxy(Class mapperInterface, SqlSession sqlSession)
{
ClassLoader classLoader = mapperInterface.getClassLoader();
Class[] interfaces = { mapperInterface };
MapperProxy proxy = new MapperProxy(sqlSession);
return Proxy.newProxyInstance(classLoader, interfaces, proxy);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
Class declaringInterface = findDeclaringInterface(proxy, method);
MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, this.sqlSession);
Object result = mapperMethod.execute(args);
if ((result == null) && (method.getReturnType().isPrimitive()) && (!method.getReturnType().equals(Void.TYPE))) {
throw new BindingException("Mapper method '" + method.getName() + "' (" + method.getDeclaringClass() + ") attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
最终通过MapperMethod的execute方法完成sqlsession的执行
public Object execute(Object[] args) {
Object result = null;
if (SqlCommandType.INSERT == this.type) {
Object param = getParam(args);
result = Integer.valueOf(this.sqlSession.insert(this.commandName, param));
} else if (SqlCommandType.UPDATE == this.type) {
Object param = getParam(args);
result = Integer.valueOf(this.sqlSession.update(this.commandName, param));
} else if (SqlCommandType.DELETE == this.type) {
Object param = getParam(args);
result = Integer.valueOf(this.sqlSession.delete(this.commandName, param));
} else if (SqlCommandType.SELECT == this.type) {
if ((this.returnsVoid) && (this.resultHandlerIndex != null)) {
executeWithResultHandler(args);
} else if (this.returnsMany) {
result = executeForMany(args);
} else if (this.returnsMap) {
result = executeForMap(args);
} else {
Object param = getParam(args);
result = this.sqlSession.selectOne(this.commandName, param);
}
} else {
throw new BindingException("Unknown execution method for: " + this.commandName);
}
return result;
}