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