Mybatis笔记一
来源:互联网 发布:数据分析师月薪 编辑:程序博客网 时间:2024/06/06 04:50
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> T selectOne(String statement) { return selectOne(statement, null); } public <T> 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 <E> List<E> 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 <E> List<E> 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> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); }
最后又转到Configuration的getMapper方法
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return this.mapperRegistry.getMapper(type, sqlSession); }
再看MapperRegistry的getMapper方法,通过MapperProxy来创建mapper的代理类
public <T> T getMapper(Class<T> 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> T newMapperProxy(Class<T> 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; }
简单来说,创建mapper接口的代理类后,被MapperProxy拦截执行invoke方法来执行sqlsession的相关操作。
0 0
- MyBatis 学习笔记一
- MyBatis学习笔记一
- mybatis学习笔记一
- Mybatis源码笔记一
- Mybatis笔记一
- MyBatis笔记一
- MyBatis笔记(一)
- Mybatis学习笔记一
- Mybatis学习笔记--(一)Mybatis基础
- MyBatis学习笔记(一)--初识MyBatis
- Mybatis JPetStore 学习笔记(一)
- mybatis学习笔记(一)
- Mybatis学习笔记(一)
- Mybatis学习笔记(一)
- MyBatis学习笔记(一)
- Mybatis框架学习笔记一
- MyBatis学习笔记(一)
- Mybatis复习笔记(一)
- Python中os和shutil模块实用方法集锦
- 【Git】常用命令commit提交,push推送,merge,添加分支branch
- SAP 子模块
- HNOI2016 最小公倍数
- eclipse下配置GO语言的开发环境
- Mybatis笔记一
- LeetCode 486. Predict the Winner
- OJ提交题目中的语言选项里G++与C++的区别
- 命名管道
- 1065. A+B and C (64bit) (20)
- CSU-1005
- 微信支付集成
- node.js第五天
- jsp request乱码