欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DefaultSqlSession第二讲-更新,刷新Statement 博客分类: Mybatis MybatisDefaultSqlSession 

程序员文章站 2024-02-12 23:42:58
...
上一篇文章中,我们讲到DefaultSqlSession的查询,今天来讲更新
//DefaultSqlSession
public class DefaultSqlSession
    implements SqlSession
{
    private Configuration configuration;
    private Executor executor;
    private boolean dirty;
    public DefaultSqlSession(Configuration configuration, Executor executor)
    {
        this.configuration = configuration;
        this.executor = executor;
        dirty = false;
    }
    //插入
     public int insert(String statement)
    {
        return insert(statement, null);
    }

    public int insert(String statement, Object parameter)
    {
       //委托给update方法
        return update(statement, parameter);
    }

    public int update(String statement)
    {
        return update(statement, null);
    }
    //删除
     public int delete(String statement)
    { 
        //委托给update
        return update(statement, null);
    }

    public int delete(String statement, Object parameter)
    {
        return update(statement, parameter);
    }
    public int update(String statement, Object parameter)
    {
        int i;
        try
        {
            dirty = true;
            org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
            //委托给executor的update
	    i = executor.update(ms, wrapCollection(parameter));
        }
    }
    //刷新Statements
    public List flushStatements()
    {
        List list;
        try
        {
            list = executor.flushStatements();
        }
    }
}

从DefaultSqlSession类,看一看出插入,删除,更新操作实际上都是调用update方法,下面
我们来看一下这个方法
public int update(String statement, Object parameter)
    {
        int i;
        try
        {
            dirty = true;
            org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
            //委托给executor的update
	    i = executor.update(ms, wrapCollection(parameter));
        }
    }

update方法委托给具体的executor,executor默认为CachingExecutor,CachingExecutor为执行器代理,具体executor
有SimpleExecutor,BatchExecutor;
下面来看SimpleExecutor
//CachingExecutor
public int update(MappedStatement ms, Object parameterObject)
        throws SQLException
    {
        flushCacheIfRequired(ms);
        return _flddelegate.update(ms, parameterObject);
    }

具体执行器SimpleExecutor
//BaseExecutor
  
public int update(MappedStatement ms, Object parameter)
        throws SQLException
    {
        ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
        if(closed)
        {
            throw new ExecutorException("Executor was closed.");
        } else
        {
            clearLocalCache();
	    //委托给doUpdate
            return doUpdate(ms, parameter);
        }
    }
    //待子类扩展
     protected abstract int doUpdate(MappedStatement mappedstatement, Object obj)
        throws SQLException;

//SimpleExecutor
public int doUpdate(MappedStatement ms, Object parameter)
        throws SQLException
    {
        Statement stmt = null;
        int i;
        Configuration configuration = ms.getConfiguration();
	//创建StatementHandler
        StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
        //创建Statement
	stmt = prepareStatement(handler, ms.getStatementLog());
	//执行查询
        i = handler.update(stmt);
	//Statement关闭
        closeStatement(stmt);
    }

//创建StatementHandler,创建Statement,执行查询,Statement关闭,上一篇我们已经说,这里就不说了,
我们看一下BatchExecutor
public class BatchExecutor extends BaseExecutor
{
    public static final int BATCH_UPDATE_RETURN_VALUE = -2147482646;
    private final List statementList = new ArrayList();//statement集合
    private final List batchResultList = new ArrayList();//结果集合
    private String currentSql;
    private MappedStatement currentStatement;
    
    public BatchExecutor(Configuration configuration, Transaction transaction)
    {
        super(configuration, transaction);
    }
     public int doUpdate(MappedStatement ms, Object parameterObject)
        throws SQLException
    {
        Configuration configuration = ms.getConfiguration();
	//创建StatementHandler
        StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);
        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql();
        Statement stmt;
        if(sql.equals(currentSql) && ms.equals(currentStatement))
        {
	   //如果sql与currentSql相等,则从statementList获取Statement
            int last = statementList.size() - 1;
            stmt = (Statement)statementList.get(last);
            BatchResult batchResult = (BatchResult)batchResultList.get(last);
            batchResult.addParameterObject(parameterObject);
        } else
        {
	    //获取连接
            java.sql.Connection connection = getConnection(ms.getStatementLog());
	    //创建statement
            stmt = handler.prepare(connection);
            currentSql = sql;
            currentStatement = ms;
	    //将statement添加到statementList
            statementList.add(stmt);
            batchResultList.add(new BatchResult(ms, sql, parameterObject));
        }
	//设置statement参数
        handler.parameterize(stmt);
	//
        handler.batch(stmt);
        return -2147482646;
    }
}

//执行statement
handler.batch(stmt);

handler为RoutingStatementHandler,RoutingStatementHandler为StatementHandler的代理类,具体可能为SimpleStatementHandler,PreparedStatementHandler,
CallableStatementHandler;
下面我们来看一下RoutingStatementHandler的batch
//RoutingStatementHandler
public class RoutingStatementHandler
    implements StatementHandler
{
 private final StatementHandler _flddelegate;
  public void batch(Statement statement)
        throws SQLException
    {
        _flddelegate.batch(statement);
    }
}

RoutingStatementHandler的batch方法实际上,是调用代理的batch方法,
//PreparedStatementHandler
public class PreparedStatementHandler extends BaseStatementHandler
{
public void batch(Statement statement)
        throws SQLException
    {
        PreparedStatement ps = (PreparedStatement)statement;
        ps.addBatch();
    }
}

//CallableStatementHandler
 
 public void batch(Statement statement)
        throws SQLException
    {
        CallableStatement cs = (CallableStatement)statement;
        cs.addBatch();
    }

具体为调用CallableStatement和PreparedStatement的批处理函数
讲到批处理,我们来看一下 DefaultSqlSession的flushStatements方法
public List flushStatements()
    {
        List list;
        try
        {
            list = executor.flushStatements();
        } 
    }

这里我们来看一下具体executor的flushStatements
//BatchExecutor
public List doFlushStatements(boolean isRollback)
        throws SQLException
    {
        List results;
        List list;
        results = new ArrayList();
        if(!isRollback)
            break MISSING_BLOCK_LABEL_83;
        list = Collections.emptyList();
        Statement stmt;
	//关闭statementList中的Statement
        for(Iterator i$ = statementList.iterator(); i$.hasNext(); closeStatement(stmt))
            stmt = (Statement)i$.next();
        //currentSql,设为null
        currentSql = null;
        statementList.clear();
        batchResultList.clear();
        return list;
    }

BatchExecutor的doFlushStatements主要是关闭statementList中的Statement,
清空statementList与batchResultList
//SimpleExecutor
public List doFlushStatements(boolean isRollback)
        throws SQLException
    {
        return Collections.emptyList();
    }

SimpleExecutor没做任何事情,从上可以看出doFlushStatements,主要是BatchExecutor会用到;
总结:
Sqlsession的update,通过CachingExecutor代理,CachingExecutor是SimpleExecutor,BatchExecutor等执行器代理执行器;CachingExecutor是调用Executor的相应方法。SimpleExecutor,BatchExecutor为实际执行器,继承BatchExecutor。SimpleExecutor更新,构造StatementHandler,获取Statement,执行查询,关闭statement。BatchExecutor的doFlushStatements主要是关闭statementList中的Statement,
清空statementList与batchResultList