2023年8月3日发(作者:)
深⼊理解MyBatis(三)—MyBatis的Update操作执⾏流程深⼊理解MyBatis(三)—MyBatis的Update操作执⾏流程通过配置⽂件的解析以及Configuration对象的⽣成,MyBatis完成了初始化;初始化完成后通过获取的SqlSessionFactory,可以得到SqlSession⽤来进⾏动态操作;MyBatis中的insert操作,delete操作,update操作实质上底层都是调⽤update;本⽂以insert操作为例分析update的具体执⾏流程;个⼈主页:
原⽂地址:(1) 会话Session的创建通过初始化获取的SessionFactory创建会话对象SqlSession session = ssion();调⽤openSessionFromDataSource()⽅法执⾏创建逻辑public SqlSession openSession() { return ssionFromDataSource(aultExecutorType(), (TransactionIsolationLevel)null, false);}在openSessionFromDataSource()⽅法中创建Executor实例,具体的SQL操作都是通过executor执⾏的⾸先从Configuration中获取Encironment对象,其中包含了数据源和相应的事务的配置根据Encironment对象创建事务⼯⼚transactionFactory,进⽽创建事务对象transaction根据产⽣的事务对象创建executor执⾏器对象,⽤来执⾏具体的SQL操作;将executor封装到DefaultSqlSession对象中返回中private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; DefaultSqlSession var8; try { Environment e = ironment(); TransactionFactory transactionFactory = nsactionFactoryFromEnvironment(e); tx = nsaction(aSource(), level, autoCommit); Executor executor = cutor(tx, execType); var8 = new DefaultSqlSession(uration, executor, autoCommit); } catch (Exception var12) { ransaction(tx); throw ception("Error opening session. Cause: " + var12, var12); } finally { ce().reset(); } return var8;}根据传⼊的transaction事务实例创建executor实例,DefaultSqlSession将主要的操作交给executor执⾏;executor有三种类型:BatchExecutor,ReuseExecutor和simpleExecutor;BatchExecutor专门⽤来执⾏批处理;ReuseExecutor会重⽤statement执⾏sqi操作;simpleExecutor只是简单执⾏sql语句;默认是simpleExecutor;如果开启catch缓存的话会利⽤装饰器模式创建CachingExecutor,CachingExecutor在查询数据库之前会先查询缓存;public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null?tExecutorType:executorType; executorType = executorType == null?:executorType; Object executor; if( == executorType) { executor = new BatchExecutor(this, transaction); } else if( == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if(nabled) { executor = new CachingExecutor((Executor)executor); } Executor executor1 = (Executor)All(executor); return executor1;}(2) Insert⽅法执⾏流程1. 创建执⾏器Executor通过openSession()⽅法创建⼀个SqlSession的实例DefaultSqlSession作为具体SQL执⾏的⼊⼝,DefaultSqlSession对象中封装着属性Configuration,Executor,autoCommit等;public int insert(String statement) { return (statement, (Object)null);}public int insert(String statement, Object parameter) { return (statement, parameter);}insert操作是通过调⽤update语句进⾏的相关逻辑,delete操作也是通过调⽤update实现的具体逻辑;根据statement从configuration中获取到相应的MappedStatement对象(在初始化中已经解析加载到configuration中)对参数parameter中的集合进⾏处理;public int update(String statement, Object parameter) { int var4; try { = true; MappedStatement e = pedStatement(statement); var4 = (e, llection(parameter)); } catch (Exception var8) { throw ception("Error updating database. Cause: " + var8, var8); } finally { ce().reset(); } return var4;}Executor最终将MapperStatement的执⾏委托给了StatementHandler;具体的执⾏流程:获取⼀个connection数据库连接;调⽤e()⽅法获取⼀个statement调⽤terize⽅法设置sql执⾏时候需要的参数调⽤()⽅法执⾏具体sql指令public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt = null; int var6; try { Configuration configuration = figuration(); StatementHandler handler = tementHandler(this, ms, parameter, T, (ResultHandler)null, (BoundSql) stmt = eStatement(handler, tementLog()); var6 = (stmt); } finally { tatement(stmt); } return var6;}调⽤prepareStatement()⽅法获取statement,类似于JDBC的tement();private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Connection connection = nection(statementLog); Statement stmt = e(connection, eout()); terize(stmt); return stmt;}2. 获取Connection数据库连接MyBatis在底层维护了⼀个简单的数据库连接池⽤来管理数据库连接,⽤来复⽤数据库连接避免连接的重复创建造成的资源浪费;SimpleExecutor中的getConnection()⽅法最终通过调⽤openConnection()实现,openConnection()⽅法中调⽤dataSource中的getConnection()⽅法获取连接protected void openConnection() throws SQLException { if (gEnabled()) { ("Opening JDBC Connection"); } connection = nection(); if (level != null) { nsactionIsolation(el()); } setDesiredAutoCommit(autoCommmit);}调⽤datasource中的popConnection()⽅法从数据库连接池中获取连接return popConnection(rname(), sword()).getProxyConnection();MyBatis底层维护了⼀个数据库连接池主要类是datasource包下的PoolDataSource和PoolConnection,通过调⽤popConnection()⽅法从数据库连接池中尝试获取连接;在数据库连接池中idleConnections⽤于存放空闲数据库连接,c⽤于存放创建完成可以使⽤的数据库连接;调⽤popConnenction()⽅法会尝试先从idleConnections中获取空闲连接,如果idleConnections为空,则判断创建的数据库连接是否超过连接池最⼤连接数,如果未超过则创建⼀个新连接并放⼊activeConnections中;如果超过则从activeConnections列表中取出第⼀个判断是否超时,如果超时则回滚具体操作,然后创建⼀个新的数据连接放⼊activeConnections中;如果未超时则当前线程await()等待等待被唤醒;private PooledConnection popConnection(String username, String password) throws SQLException { boolean countedWait = false; PooledConnection conn = null; long t = tTimeMillis(); int localBadConnectionCount = 0; while (conn == null) { synchronized (state) { if (!y()) { // Pool has available connection conn = (0); if (gEnabled()) { ("Checked out connection " + lHashCode() + " from pool."); } } else { // Pool does not have available connection if (() < poolMaximumActiveConnections) { // Can create new connection conn = new PooledConnection(nection(), this); if (gEnabled()) { ("Created connection " + lHashCode() + "."); } } else { // Cannot create new connection PooledConnection oldestActiveConnection = (0); long longestCheckoutTime = ckoutTime(); if (longestCheckoutTime > poolMaximumCheckoutTime) { if (longestCheckoutTime > poolMaximumCheckoutTime) { // Can claim overdue connection dOverdueConnectionCount++; latedCheckoutTimeOfOverdueConnections += longestCheckoutTime; latedCheckoutTime += longestCheckoutTime; (oldestActiveConnection); if (!lConnection().getAutoCommit()) { try { lConnection().rollback(); } catch (SQLException e) { ("Bad connection. Could not roll back"); }
} conn = new PooledConnection(lConnection(), this); atedTimestamp(atedTimestamp()); tUsedTimestamp(tUsedTimestamp()); date(); if (gEnabled()) { ("Claimed overdue connection " + lHashCode() + "."); } } else { // Must wait try { if (!countedWait) { aitCount++; countedWait = true; } if (gEnabled()) { ("Waiting as long as " + poolTimeToWait + " milliseconds for connection."); } long wt = tTimeMillis(); (poolTimeToWait); latedWaitTime += tTimeMillis() - wt; } catch (InterruptedException e) { break; } } } } if (conn != null) { if (d()) { if (!lConnection().getAutoCommit()) { lConnection().rollback(); } nectionTypeCode(assembleConnectionTypeCode((), username, password)); ckoutTimestamp(tTimeMillis()); tUsedTimestamp(tTimeMillis()); (conn); tCount++; latedRequestTime += tTimeMillis() - t; } else { if (gEnabled()) { ("A bad connection (" + lHashCode() + ") was returned from the pool, getting another connection."); } nectionCount++; localBadConnectionCount++; conn = null; if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) { if (gEnabled()) { ("PooledDataSource: Could not get a good connection to the database."); } throw new SQLException("PooledDataSource: Could not get a good connection to the database."); } } } } } } if (conn == null) { if (gEnabled()) { ("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection."); } throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection."); } return conn;}如果idleConnections列表为空且activeConnections列表长度⼩于连接池最⼤连接数,则创建新的PoolConnection对象;具体的数据库连接的创建逻辑在doGetConnection()⽅法中,从dataSource取出数据库配置信息创建相应的数据库连接;private Connection doGetConnection(String username, String password) throws SQLException { Properties props = new Properties(); if (driverProperties != null) { (driverProperties); } if (username != null) { perty("user", username); } if (password != null) { perty("password", password); } return doGetConnection(props);}private Connection doGetConnection(Properties properties) throws SQLException { initializeDriver(); Connection connection = nection(url, properties); configureConnection(connection); return connection;}3. 为Connection⽣成代理对象创建新的PoolConnection对象,⽣成connection的代理public PooledConnection(Connection connection, PooledDataSource dataSource) { de = de(); nnection = connection; urce = dataSource; dTimestamp = tTimeMillis(); edTimestamp = tTimeMillis(); = true; onnection = (Connection) xyInstance(ssLoader(), IFACES, this);}对Connection⽣成JDK动态代理,PooledConnection本⾝就是实现了invocationHandler接⼝,在调⽤Connection的⽅法时候会通过invoke()⽅法直接调⽤⽣成的代理类的⽅法;在代理数据库连接类中会判断调⽤⽅法是否为close(),则会调⽤pushConnection()代理原来的close()⽅法;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = e(); if (de() == de() && (methodName)) { nnection(this); return null; } else { try { if (!(laringClass())) { // issue #579 toString() should never fail // throw an SQLException instead of a Runtime checkConnection(); } return (realConnection, args); } catch (Throwable t) { throw Throwable(t); } }}pushConnection()⽅法主要处理数据库连接关闭问题,当数据库连接⽤完后从activeConnections列表中移除connection,同时判断空闲列表idleConnections中的连接数量对否少于最⼤空闲数量,如果少于将connection放⼊idleConnections;如果⼤于最⼤空闲连接数⽬则调⽤原connection的close()⽅法,使连接失效;protected void pushConnection(PooledConnection conn) throws SQLException { synchronized (state) { (conn); if (d()) { if (() < poolMaximumIdleConnections && nectionTypeCode() == expectedConnectionTypeCode) { latedCheckoutTime += ckoutTime(); if (!lConnection().getAutoCommit()) { lConnection().rollback(); } PooledConnection newConn = new PooledConnection(lConnection(), this); (newConn); atedTimestamp(atedTimestamp()); tUsedTimestamp(tUsedTimestamp()); date(); if (gEnabled()) { ("Returned connection " + lHashCode() + " to pool."); } All(); } else { latedCheckoutTime += ckoutTime(); if (!lConnection().getAutoCommit()) { lConnection().rollback(); } lConnection().close(); if (gEnabled()) { ("Closed connection " + lHashCode() + "."); } date(); } } else { if (gEnabled()) { ("A bad connection (" + lHashCode() + ") attempted to return to the pool, discarding connection."); } nectionCount++; } }}4. 利⽤⽣成的Connection对象创建statement根据上⽂⽣成的数据库连接创建Statement实例对象;private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = e(connection, eout()); terize(stmt); return stmt;}@Overridepublic Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException { return e(connection, transactionTimeout);}prepare()⽅法调⽤instantiateStatement()⽅法从connection中获取Statement实例,并将超时时间绑定@Overridepublic Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException { ce().sql(()); Statement statement = null; try { statement = instantiateStatement(connection); setStatementTimeout(statement, transactionTimeout); setFetchSize(statement); return statement; } catch (SQLException e) { closeStatement(statement); throw e; } catch (Exception e) { closeStatement(statement); throw new ExecutorException("Error preparing statement. Cause: " + e, e); }}从boundSql中获取待执⾏的sql,调⽤ement(sql)⽣成Statement对象@Overrideprotected Statement instantiateStatement(Connection connection) throws SQLException { String sql = (); if (Generator() instanceof Jdbc3KeyGenerator) { String[] keyColumnNames = Columns(); if (keyColumnNames == null) { return eStatement(sql, _GENERATED_KEYS); } else { return eStatement(sql, keyColumnNames); } } else if (ultSetType() != null) { return eStatement(sql, ultSetType().getValue(), _READ_ONLY); } else { return eStatement(sql); }}5. 对⽣成的Statement实例进⾏参数设置通过connection实例获取statement后需要进⾏参数设置private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = e(connection, eout()); terize(stmt); return stmt;}@Overridepublic void parameterize(Statement statement) throws SQLException { terize(statement);}@Overridepublic void parameterize(Statement statement) throws SQLException { ameters((PreparedStatement) statement);}从boundSql中获取参数列表parameterMapping,调⽤setParameter()⽅法进⾏参数设置;@Overridepublic void setParameters(PreparedStatement ps) { ce().activity("setting parameters").object(ameterMap().getId()); List
2023年8月3日发(作者:)
深⼊理解MyBatis(三)—MyBatis的Update操作执⾏流程深⼊理解MyBatis(三)—MyBatis的Update操作执⾏流程通过配置⽂件的解析以及Configuration对象的⽣成,MyBatis完成了初始化;初始化完成后通过获取的SqlSessionFactory,可以得到SqlSession⽤来进⾏动态操作;MyBatis中的insert操作,delete操作,update操作实质上底层都是调⽤update;本⽂以insert操作为例分析update的具体执⾏流程;个⼈主页:
原⽂地址:(1) 会话Session的创建通过初始化获取的SessionFactory创建会话对象SqlSession session = ssion();调⽤openSessionFromDataSource()⽅法执⾏创建逻辑public SqlSession openSession() { return ssionFromDataSource(aultExecutorType(), (TransactionIsolationLevel)null, false);}在openSessionFromDataSource()⽅法中创建Executor实例,具体的SQL操作都是通过executor执⾏的⾸先从Configuration中获取Encironment对象,其中包含了数据源和相应的事务的配置根据Encironment对象创建事务⼯⼚transactionFactory,进⽽创建事务对象transaction根据产⽣的事务对象创建executor执⾏器对象,⽤来执⾏具体的SQL操作;将executor封装到DefaultSqlSession对象中返回中private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; DefaultSqlSession var8; try { Environment e = ironment(); TransactionFactory transactionFactory = nsactionFactoryFromEnvironment(e); tx = nsaction(aSource(), level, autoCommit); Executor executor = cutor(tx, execType); var8 = new DefaultSqlSession(uration, executor, autoCommit); } catch (Exception var12) { ransaction(tx); throw ception("Error opening session. Cause: " + var12, var12); } finally { ce().reset(); } return var8;}根据传⼊的transaction事务实例创建executor实例,DefaultSqlSession将主要的操作交给executor执⾏;executor有三种类型:BatchExecutor,ReuseExecutor和simpleExecutor;BatchExecutor专门⽤来执⾏批处理;ReuseExecutor会重⽤statement执⾏sqi操作;simpleExecutor只是简单执⾏sql语句;默认是simpleExecutor;如果开启catch缓存的话会利⽤装饰器模式创建CachingExecutor,CachingExecutor在查询数据库之前会先查询缓存;public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null?tExecutorType:executorType; executorType = executorType == null?:executorType; Object executor; if( == executorType) { executor = new BatchExecutor(this, transaction); } else if( == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if(nabled) { executor = new CachingExecutor((Executor)executor); } Executor executor1 = (Executor)All(executor); return executor1;}(2) Insert⽅法执⾏流程1. 创建执⾏器Executor通过openSession()⽅法创建⼀个SqlSession的实例DefaultSqlSession作为具体SQL执⾏的⼊⼝,DefaultSqlSession对象中封装着属性Configuration,Executor,autoCommit等;public int insert(String statement) { return (statement, (Object)null);}public int insert(String statement, Object parameter) { return (statement, parameter);}insert操作是通过调⽤update语句进⾏的相关逻辑,delete操作也是通过调⽤update实现的具体逻辑;根据statement从configuration中获取到相应的MappedStatement对象(在初始化中已经解析加载到configuration中)对参数parameter中的集合进⾏处理;public int update(String statement, Object parameter) { int var4; try { = true; MappedStatement e = pedStatement(statement); var4 = (e, llection(parameter)); } catch (Exception var8) { throw ception("Error updating database. Cause: " + var8, var8); } finally { ce().reset(); } return var4;}Executor最终将MapperStatement的执⾏委托给了StatementHandler;具体的执⾏流程:获取⼀个connection数据库连接;调⽤e()⽅法获取⼀个statement调⽤terize⽅法设置sql执⾏时候需要的参数调⽤()⽅法执⾏具体sql指令public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt = null; int var6; try { Configuration configuration = figuration(); StatementHandler handler = tementHandler(this, ms, parameter, T, (ResultHandler)null, (BoundSql) stmt = eStatement(handler, tementLog()); var6 = (stmt); } finally { tatement(stmt); } return var6;}调⽤prepareStatement()⽅法获取statement,类似于JDBC的tement();private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Connection connection = nection(statementLog); Statement stmt = e(connection, eout()); terize(stmt); return stmt;}2. 获取Connection数据库连接MyBatis在底层维护了⼀个简单的数据库连接池⽤来管理数据库连接,⽤来复⽤数据库连接避免连接的重复创建造成的资源浪费;SimpleExecutor中的getConnection()⽅法最终通过调⽤openConnection()实现,openConnection()⽅法中调⽤dataSource中的getConnection()⽅法获取连接protected void openConnection() throws SQLException { if (gEnabled()) { ("Opening JDBC Connection"); } connection = nection(); if (level != null) { nsactionIsolation(el()); } setDesiredAutoCommit(autoCommmit);}调⽤datasource中的popConnection()⽅法从数据库连接池中获取连接return popConnection(rname(), sword()).getProxyConnection();MyBatis底层维护了⼀个数据库连接池主要类是datasource包下的PoolDataSource和PoolConnection,通过调⽤popConnection()⽅法从数据库连接池中尝试获取连接;在数据库连接池中idleConnections⽤于存放空闲数据库连接,c⽤于存放创建完成可以使⽤的数据库连接;调⽤popConnenction()⽅法会尝试先从idleConnections中获取空闲连接,如果idleConnections为空,则判断创建的数据库连接是否超过连接池最⼤连接数,如果未超过则创建⼀个新连接并放⼊activeConnections中;如果超过则从activeConnections列表中取出第⼀个判断是否超时,如果超时则回滚具体操作,然后创建⼀个新的数据连接放⼊activeConnections中;如果未超时则当前线程await()等待等待被唤醒;private PooledConnection popConnection(String username, String password) throws SQLException { boolean countedWait = false; PooledConnection conn = null; long t = tTimeMillis(); int localBadConnectionCount = 0; while (conn == null) { synchronized (state) { if (!y()) { // Pool has available connection conn = (0); if (gEnabled()) { ("Checked out connection " + lHashCode() + " from pool."); } } else { // Pool does not have available connection if (() < poolMaximumActiveConnections) { // Can create new connection conn = new PooledConnection(nection(), this); if (gEnabled()) { ("Created connection " + lHashCode() + "."); } } else { // Cannot create new connection PooledConnection oldestActiveConnection = (0); long longestCheckoutTime = ckoutTime(); if (longestCheckoutTime > poolMaximumCheckoutTime) { if (longestCheckoutTime > poolMaximumCheckoutTime) { // Can claim overdue connection dOverdueConnectionCount++; latedCheckoutTimeOfOverdueConnections += longestCheckoutTime; latedCheckoutTime += longestCheckoutTime; (oldestActiveConnection); if (!lConnection().getAutoCommit()) { try { lConnection().rollback(); } catch (SQLException e) { ("Bad connection. Could not roll back"); }
} conn = new PooledConnection(lConnection(), this); atedTimestamp(atedTimestamp()); tUsedTimestamp(tUsedTimestamp()); date(); if (gEnabled()) { ("Claimed overdue connection " + lHashCode() + "."); } } else { // Must wait try { if (!countedWait) { aitCount++; countedWait = true; } if (gEnabled()) { ("Waiting as long as " + poolTimeToWait + " milliseconds for connection."); } long wt = tTimeMillis(); (poolTimeToWait); latedWaitTime += tTimeMillis() - wt; } catch (InterruptedException e) { break; } } } } if (conn != null) { if (d()) { if (!lConnection().getAutoCommit()) { lConnection().rollback(); } nectionTypeCode(assembleConnectionTypeCode((), username, password)); ckoutTimestamp(tTimeMillis()); tUsedTimestamp(tTimeMillis()); (conn); tCount++; latedRequestTime += tTimeMillis() - t; } else { if (gEnabled()) { ("A bad connection (" + lHashCode() + ") was returned from the pool, getting another connection."); } nectionCount++; localBadConnectionCount++; conn = null; if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) { if (gEnabled()) { ("PooledDataSource: Could not get a good connection to the database."); } throw new SQLException("PooledDataSource: Could not get a good connection to the database."); } } } } } } if (conn == null) { if (gEnabled()) { ("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection."); } throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection."); } return conn;}如果idleConnections列表为空且activeConnections列表长度⼩于连接池最⼤连接数,则创建新的PoolConnection对象;具体的数据库连接的创建逻辑在doGetConnection()⽅法中,从dataSource取出数据库配置信息创建相应的数据库连接;private Connection doGetConnection(String username, String password) throws SQLException { Properties props = new Properties(); if (driverProperties != null) { (driverProperties); } if (username != null) { perty("user", username); } if (password != null) { perty("password", password); } return doGetConnection(props);}private Connection doGetConnection(Properties properties) throws SQLException { initializeDriver(); Connection connection = nection(url, properties); configureConnection(connection); return connection;}3. 为Connection⽣成代理对象创建新的PoolConnection对象,⽣成connection的代理public PooledConnection(Connection connection, PooledDataSource dataSource) { de = de(); nnection = connection; urce = dataSource; dTimestamp = tTimeMillis(); edTimestamp = tTimeMillis(); = true; onnection = (Connection) xyInstance(ssLoader(), IFACES, this);}对Connection⽣成JDK动态代理,PooledConnection本⾝就是实现了invocationHandler接⼝,在调⽤Connection的⽅法时候会通过invoke()⽅法直接调⽤⽣成的代理类的⽅法;在代理数据库连接类中会判断调⽤⽅法是否为close(),则会调⽤pushConnection()代理原来的close()⽅法;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = e(); if (de() == de() && (methodName)) { nnection(this); return null; } else { try { if (!(laringClass())) { // issue #579 toString() should never fail // throw an SQLException instead of a Runtime checkConnection(); } return (realConnection, args); } catch (Throwable t) { throw Throwable(t); } }}pushConnection()⽅法主要处理数据库连接关闭问题,当数据库连接⽤完后从activeConnections列表中移除connection,同时判断空闲列表idleConnections中的连接数量对否少于最⼤空闲数量,如果少于将connection放⼊idleConnections;如果⼤于最⼤空闲连接数⽬则调⽤原connection的close()⽅法,使连接失效;protected void pushConnection(PooledConnection conn) throws SQLException { synchronized (state) { (conn); if (d()) { if (() < poolMaximumIdleConnections && nectionTypeCode() == expectedConnectionTypeCode) { latedCheckoutTime += ckoutTime(); if (!lConnection().getAutoCommit()) { lConnection().rollback(); } PooledConnection newConn = new PooledConnection(lConnection(), this); (newConn); atedTimestamp(atedTimestamp()); tUsedTimestamp(tUsedTimestamp()); date(); if (gEnabled()) { ("Returned connection " + lHashCode() + " to pool."); } All(); } else { latedCheckoutTime += ckoutTime(); if (!lConnection().getAutoCommit()) { lConnection().rollback(); } lConnection().close(); if (gEnabled()) { ("Closed connection " + lHashCode() + "."); } date(); } } else { if (gEnabled()) { ("A bad connection (" + lHashCode() + ") attempted to return to the pool, discarding connection."); } nectionCount++; } }}4. 利⽤⽣成的Connection对象创建statement根据上⽂⽣成的数据库连接创建Statement实例对象;private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = e(connection, eout()); terize(stmt); return stmt;}@Overridepublic Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException { return e(connection, transactionTimeout);}prepare()⽅法调⽤instantiateStatement()⽅法从connection中获取Statement实例,并将超时时间绑定@Overridepublic Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException { ce().sql(()); Statement statement = null; try { statement = instantiateStatement(connection); setStatementTimeout(statement, transactionTimeout); setFetchSize(statement); return statement; } catch (SQLException e) { closeStatement(statement); throw e; } catch (Exception e) { closeStatement(statement); throw new ExecutorException("Error preparing statement. Cause: " + e, e); }}从boundSql中获取待执⾏的sql,调⽤ement(sql)⽣成Statement对象@Overrideprotected Statement instantiateStatement(Connection connection) throws SQLException { String sql = (); if (Generator() instanceof Jdbc3KeyGenerator) { String[] keyColumnNames = Columns(); if (keyColumnNames == null) { return eStatement(sql, _GENERATED_KEYS); } else { return eStatement(sql, keyColumnNames); } } else if (ultSetType() != null) { return eStatement(sql, ultSetType().getValue(), _READ_ONLY); } else { return eStatement(sql); }}5. 对⽣成的Statement实例进⾏参数设置通过connection实例获取statement后需要进⾏参数设置private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = e(connection, eout()); terize(stmt); return stmt;}@Overridepublic void parameterize(Statement statement) throws SQLException { terize(statement);}@Overridepublic void parameterize(Statement statement) throws SQLException { ameters((PreparedStatement) statement);}从boundSql中获取参数列表parameterMapping,调⽤setParameter()⽅法进⾏参数设置;@Overridepublic void setParameters(PreparedStatement ps) { ce().activity("setting parameters").object(ameterMap().getId()); List
发布评论