深入理解MyBatis(三)—MyBatis的Update操作执行流程

更新时间:2023-05-12 02:20:37 阅读: 评论:0

深⼊理解MyBatis(三)—MyBatis的Update操作执⾏流程
深⼊理解MyBatis(三)—MyBatis的Update操作执⾏流程
通过配置⽂件的解析以及Configuration对象的⽣成,MyBatis完成了初始化;初始化完成后通过获取的SqlSessionFactory,可以得到SqlSession⽤来进⾏动态操作;
MyBatis中的inrt操作,delete操作,update操作实质上底层都是调⽤update;本⽂以inrt操作为例分析update的具体执⾏流程;
个⼈主页:
原⽂地址:
(1) 会话Session的创建
通过初始化获取的SessionFactory创建会话对象
SqlSession ssion = ssionFactory.openSession();
调⽤openSessionFromDataSource()⽅法执⾏创建逻辑
public SqlSession openSession() {
return this.DefaultExecutorType(), (TransactionIsolationLevel)null, fal);
}
在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 = Environment();
TransactionFactory transactionFactory = TransactionFactoryFromEnvironment(e);
tx = DataSource(), level, autoCommit);
Executor executor = wExecutor(tx, execType);
var8 = new figuration, executor, autoCommit);
} catch (Exception var12) {
this.cloTransaction(tx);
throw ExceptionFactory.wrapException("Error opening ssion.  Cau: " + var12, var12);
} finally {
ErrorContext.instance().ret();
}
return var8;
}
根据传⼊的transaction事务实例创建executor实例,DefaultSqlSession将主要的操作交给executor执⾏;
executor有三种类型:BatchExecutor,ReuExecutor和simpleExecutor;BatchExecutor专门⽤来执⾏批处理;
ReuExecutor会重⽤statement执⾏sqi操作;simpleExecutor只是简单执⾏sql语句;默认是simpleExecutor;
如果开启catch缓存的话会利⽤装饰器模式创建CachingExecutor,CachingExecutor在查询数据库之前会先查询缓存;
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null?this.defaultExecutorType:executorType;
executorType = executorType == null?ExecutorType.SIMPLE:executorType;
Object executor;
if(ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} el if(ExecutorType.REUSE == executorType) {
executor = new ReuExecutor(this, transaction);
} el {
executor = new SimpleExecutor(this, transaction);
}
if(this.cacheEnabled) {
executor = new CachingExecutor((Executor)executor);
}
Executor executor1 = (Executor)this.interceptorChain.pluginAll(executor);
return executor1;
}
(2) Inrt⽅法执⾏流程
1. 创建执⾏器Executor
通过openSession()⽅法创建⼀个SqlSession的实例DefaultSqlSession作为具体SQL执⾏的⼊⼝,DefaultSqlSession对象中封装着属性Configuration,Executor,autoCommit等;
public int inrt(String statement) {
return this.inrt(statement, (Object)null);
}
public int inrt(String statement, Object parameter) {
return this.update(statement, parameter);
}
inrt操作是通过调⽤update语句进⾏的相关逻辑,delete操作也是通过调⽤update实现的具体逻辑;
根据statement从configuration中获取到相应的MappedStatement对象(在初始化中已经解析加载到configuration中)
对参数parameter中的集合进⾏处理;
public int update(String statement, Object parameter) {
int var4;
try {
this.dirty = true;
MappedStatement e = MappedStatement(statement);
var4 = utor.update(e, this.wrapCollection(parameter));
} catch (Exception var8) {
throw ExceptionFactory.wrapException("Error updating databa.  Cau: " + var8, var8);
} finally {
ErrorContext.instance().ret();
}
return var4;
}
Executor最终将MapperStatement的执⾏委托给了StatementHandler;具体的执⾏流程:
获取⼀个connection数据库连接;
调⽤StatementHandler.prepare()⽅法获取⼀个statement
调⽤StatementHandler.parameterize⽅法设置sql执⾏时候需要的参数
调⽤StatementHandler.update()⽅法执⾏具体sql指令
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
int var6;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = wStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)        stmt = this.prepareStatement(handler, ms.getStatementLog());
var6 = handler.update(stmt);
} finally {
this.cloStatement(stmt);
}
return var6;
}
调⽤prepareStatement()⽅法获取statement,类似于JDBC的Statement();
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Connection connection = Connection(statementLog);
Statement stmt = handler.prepare(connection, Timeout());
handler.parameterize(stmt);
return stmt;
}
2. 获取Connection数据库连接
MyBatis在底层维护了⼀个简单的数据库连接池⽤来管理数据库连接,⽤来复⽤数据库连接避免连接的重复创建造成的资源浪费;
SimpleExecutor中的getConnection()⽅法最终通过调⽤openConnection()实现,openConnection()⽅法中调⽤dataSource中的getConnection()⽅法获取连接
protected void openConnection() throws SQLException {
if (log.isDebugEnabled()) {
log.debug("Opening JDBC Connection");
}
connection = Connection();
if (level != null) {
connection.Level());
}
tDesiredAutoCommit(autoCommmit);
}
调⽤datasource中的popConnection()⽅法从数据库连接池中获取连接
return Urname(), Password()).getProxyConnection();
MyBatis底层维护了⼀个数据库连接池主要类是datasource包下的PoolDataSource和PoolConnection,通过调⽤
popConnection()⽅法从数据库连接池中尝试获取连接;
在数据库连接池中idleConnections⽤于存放空闲数据库连接,c⽤于存放创建完成可以使⽤的数据库连接;
调⽤popConnenction()⽅法会尝试先从idleConnections中获取空闲连接,如果idleConnections为空,
则判断创建的数据库连接是否超过连接池最⼤连接数,如果未超过则创建⼀个新连接并放⼊activeConnections中;如果超过则从activeConnections列表中取出第⼀个判断是否超时,如果超时则回滚具体操作,然后创建⼀个新的数据连接放⼊activeConnections中;如果未超时则当前线程await()等待等待被唤醒;
private PooledConnection popConnection(String urname, String password) throws SQLException {
boolean countedWait = fal;
PooledConnection conn = null;
long t = System.currentTimeMillis();
int localBadConnectionCount = 0;
while (conn == null) {
synchronized (state) {
if (!state.idleConnections.isEmpty()) {
// Pool has available connection
conn = ve(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + RealHashCode() + " from pool.");
}
} el {
// Pool does not have available connection
if (state.activeConnections.size() < poolMaximumActiveConnections) {
// Can create new connection
conn = new Connection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + RealHashCode() + ".");
}
} el {
// Cannot create new connection
PooledConnection oldestActiveConnection = (0);
long longestCheckoutTime = CheckoutTime();
if (longestCheckoutTime > poolMaximumCheckoutTime) {
if (longestCheckoutTime > poolMaximumCheckoutTime) {
// Can claim overdue connection
state.claimedOverdueConnectionCount++;
state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
state.accumulatedCheckoutTime += longestCheckoutTime;
ve(oldestActiveConnection);
if (!RealConnection().getAutoCommit()) {
try {
} catch (SQLException e) {
log.debug("Bad connection. Could not roll back");
}
}
conn = new RealConnection(), this);
conn.CreatedTimestamp());
conn.LastUdTimestamp());
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + RealHashCode() + ".");
}
} el {
// Must wait
try {
if (!countedWait) {
state.hadToWaitCount++;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + poolTimeToWait + " milliconds for connection.");
}
long wt = System.currentTimeMillis();
state.wait(poolTimeToWait);
state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException e) {
break;
}
}
}
}
if (conn != null) {
if (conn.isValid()) {
if (!RealConnection().getAutoCommit()) {
}
conn.tConnectionTypeCode(Url(), urname, password));
conn.tCheckoutTimestamp(System.currentTimeMillis());
conn.tLastUdTimestamp(System.currentTimeMillis());
state.activeConnections.add(conn);
state.accumulatedRequestTime += System.currentTimeMillis() - t;
} el {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + RealHashCode() + ") was returned from the pool, getting another connection.");          }
state.badConnectionCount++;
localBadConnectionCount++;
conn = null;
if (localBadConnectionCount > (poolMaximumIdleConnections + 3)) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Could not get a good connection to the databa.");
}
throw new SQLException("PooledDataSource: Could not get a good connection to the databa.");
}
}
}
}

本文发布于:2023-05-12 02:20:37,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/593475.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:创建   连接   操作
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图