Mybatis笔记一

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);
  }

最后又转到Configuration的getMapper方法

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;
  }

简单来说,创建mapper接口的代理类后,被MapperProxy拦截执行invoke方法来执行sqlsession的相关操作。






















你可能感兴趣的:(java)