mybatis源码解析4---sqlsession解析

Lucky帅小武      2022-04-08     614

关键词:

由之前解析可知,mybatis启动的时候会加载XML配置文件解析生成全局配置对象Configuration对象,SqlSessionFactoryBuilder类会根据Configuration对象创建一个DefaultSqlSessionFactory对象,而DefaultSqlSessionFactory对象实现了SqlSessionFactory中的创建SqlSession的方法,最终新建了一个SqlSession接口的默认实现类DefaultSqlSession,现在先来了解下SqlSession以及它的实现类

SqlSession解析

SqlSession位于mybatis包的org.apache.ibatis.session目录下,字面意思就是sql的会话,用于程序和数据库直接的sql会话,程序执行一次数据库操作就需要创建一个sqlSession,操作结束即关闭sqlSession;

既然是程序和数据库之间的会话,那么sqlSession接口的方法应该是程序和数据库都容易理解的,sqlSession中定义的方法都是关于数据库操作的方法,源码如下:

 

 1 package org.apache.ibatis.session;
 2 
 3 import java.io.Closeable;
 4 import java.sql.Connection;
 5 import java.util.List;
 6 import java.util.Map;
 7 
 8 import org.apache.ibatis.cursor.Cursor;
 9 import org.apache.ibatis.executor.BatchResult;
10 
11 public interface SqlSession extends Closeable {
12 
13     //根据Sql语句查询单条记录
14   <T> T selectOne(String statement);
15   <T> T selectOne(String statement, Object parameter);//根据Sql语句和参数查询单条记录
16 
17   //根据Sql语句查询多条记录
18   <E> List<E> selectList(String statement);
19   <E> List<E> selectList(String statement, Object parameter);//根据Sql语句和参数查询多条记录
20   <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);//根据Sql语句和参数以及分页参数查询多条记录
21 
22    //selectMap和selectList原理一样,只是将结果集映射成Map对象返回
23   <K, V> Map<K, V> selectMap(String statement, String mapKey);
24   <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
25   <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
26 
27   //返回游标对象
28   <T> Cursor<T> selectCursor(String statement);
29   <T> Cursor<T> selectCursor(String statement, Object parameter);
30   <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);
31 
32   //查询的结果对象由指定的ResultHandler处理
33   void select(String statement, Object parameter, ResultHandler handler);
34   void select(String statement, ResultHandler handler);
35   void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
36 
37   //执行insert语句
38   int insert(String statement);
39   int insert(String statement, Object parameter);
40 
41   //执行update语句
42   int update(String statement);
43   int update(String statement, Object parameter);
44 
45   //执行delete语句
46   int delete(String statement);
47   int delete(String statement, Object parameter);
48 
49   //提交事务
50   void commit();
51   void commit(boolean force);
52 
53   //事务回滚
54   void rollback();
55   void rollback(boolean force);
56 
57   //将请求刷新到数据库
58   List<BatchResult> flushStatements();
59 
60   //关闭sqlSession
61   @Override
62   void close();
63 
64   //清除缓存  
65   void clearCache();
66   
67   //获取Configuration对象
68   Configuration getConfiguration();
69 
70   //获取Type对象的Mapper对象
71   <T> T getMapper(Class<T> type);
72 
73   //获取sqlSession对象的数据库连接
74   Connection getConnection();
75 }

SqlSession中的方法全是和数据库相关的增删改查以及事务的提交方法。

SqlSession有三个实现类,除了默认的DefaultSqlSession之外,还有SqlSessionManager和SqlSessionTemplate

接下来先看下SqlSession默认的实现类DefaultSqlSession是如何实现的。

 

DefaultSqlSession类解析

DefaultSqlSession有5个属性和2个构造方法如下:

 1   private Configuration configuration;//全局配置
 2   private Executor executor;//执行器
 3 
 4   private boolean autoCommit;//自动提交标识
 5   private boolean dirty;
 6   private List<Cursor<?>> cursorList;//游标列表
 7 
 8   public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
 9     this.configuration = configuration;
10     this.executor = executor;
11     this.dirty = false;
12     this.autoCommit = autoCommit;
13   }
14 
15   public DefaultSqlSession(Configuration configuration, Executor executor) {
16     this(configuration, executor, false);
17   }

下面以select方法为例

 1 @Override
 2   public <T> T selectOne(String statement) {
 3     return this.<T>selectOne(statement, null);
 4   }
 5 
 6   @Override
 7   public <T> T selectOne(String statement, Object parameter) {
 8     // Popular vote was to return null on 0 results and throw exception on too many.
 9     List<T> list = this.<T>selectList(statement, parameter);
10     if (list.size() == 1) {
11       return list.get(0);
12     } else if (list.size() > 1) {
13       throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
14     } else {
15       return null;
16     }
17   }

很明显selectOne的方法最终都是调用了selectList方法,然后取唯一的一条数据返回。那在看看selectList相关的代码

 1 @Override
 2   public <E> List<E> selectList(String statement) {
 3     return this.selectList(statement, null);
 4   }
 5 
 6   @Override
 7   public <E> List<E> selectList(String statement, Object parameter) {
 8     return this.selectList(statement, parameter, RowBounds.DEFAULT);
 9   }
10 
11   @Override
12   public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
13     try {
14       MappedStatement ms = configuration.getMappedStatement(statement);
15       return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
16     } catch (Exception e) {
17       throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
18     } finally {
19       ErrorContext.instance().reset();
20     }
21   }

共有三个selectList方法,最终都是调用了最后一个selectList方法,这里有三个参数:statement是sql语句;parameter是传入的参数;RowBounds是和分页相关的参数

RowBounds源码如下:

 1 package org.apache.ibatis.session;
 2 
 3 /**
 4  * @author Clinton Begin
 5  */
 6 public class RowBounds {
 7 
 8   public static final int NO_ROW_OFFSET = 0;
 9   public static final int NO_ROW_LIMIT = Integer.MAX_VALUE; //int的最大值
10   public static final RowBounds DEFAULT = new RowBounds();
11 
12   private int offset;
13   private int limit;
14 
15   public RowBounds() {
16     this.offset = NO_ROW_OFFSET;
17     this.limit = NO_ROW_LIMIT;
18   }
19 
20   public RowBounds(int offset, int limit) {
21     this.offset = offset;
22     this.limit = limit;
23   }
24 
25   public int getOffset() {
26     return offset;
27   }
28 
29   public int getLimit() {
30     return limit;
31   }
32 
33 }

RowBounds的两个属性:offSet是指查询数据时从多少位置开始查询,limit是指返回数据的调试,默认是从0位置开始查询到Integer的最大值,相关于默认是不做分页处理;

回到正题,selectList最后执行的方法中执行了两行代码

1 MappedStatement ms = configuration.getMappedStatement(statement);
2 return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);

调用configuration的getMapped的Statement方法获取MappedStatement对象,然后调用执行器executor的query方法获取查询结果。

这是select方法,再来看看其他的insert、update、delete方法

 1 @Override
 2   public int insert(String statement) {
 3     return insert(statement, null);
 4   }
 5 
 6   @Override
 7   public int insert(String statement, Object parameter) {
 8     return update(statement, parameter);
 9   }
10 
11   @Override
12   public int update(String statement) {
13     return update(statement, null);
14   }
15 
16   @Override
17   public int update(String statement, Object parameter) {
18     try {
19       dirty = true;
20       MappedStatement ms = configuration.getMappedStatement(statement);
21       return executor.update(ms, wrapCollection(parameter));
22     } catch (Exception e) {
23       throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
24     } finally {
25       ErrorContext.instance().reset();
26     }
27   }
28 
29   @Override
30   public int delete(String statement) {
31     return update(statement, null);
32   }
33 
34   @Override
35   public int delete(String statement, Object parameter) {
36     return update(statement, parameter);
37   }

可以看出SqlSession的insert和delete的方法最终都是调用了update方法,而update方法最终也是调用了Executor的update

 

由此可得出结论sqlSession虽然叫程序和数据库之间的SQL会话,但是它并没有具体去执行sql语句,最终的sql语句的执行是由执行器Executor执行的,而SqlSession的作用只是创建了MappedStatement对象以及调用执行器去执行SQL

其他的commit、rollback方法同样最终都是调用的执行器Executor的对应的方法,那么接下来就去了解下执行器Executor是干嘛的,以及SqlSession创建的MappedStatement又是什么?

 

DefaultSqlSession完整源码如下:

技术分享图片
  1 /**
  2  *    Copyright 2009-2015 the original author or authors.
  3  *
  4  *    Licensed under the Apache License, Version 2.0 (the "License");
  5  *    you may not use this file except in compliance with the License.
  6  *    You may obtain a copy of the License at
  7  *
  8  *       http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  *    Unless required by applicable law or agreed to in writing, software
 11  *    distributed under the License is distributed on an "AS IS" BASIS,
 12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  *    See the License for the specific language governing permissions and
 14  *    limitations under the License.
 15  */
 16 package org.apache.ibatis.session.defaults;
 17 
 18 import java.io.IOException;
 19 import java.sql.Connection;
 20 import java.sql.SQLException;
 21 import java.util.ArrayList;
 22 import java.util.Collection;
 23 import java.util.HashMap;
 24 import java.util.List;
 25 import java.util.Map;
 26 
 27 import org.apache.ibatis.binding.BindingException;
 28 import org.apache.ibatis.cursor.Cursor;
 29 import org.apache.ibatis.exceptions.ExceptionFactory;
 30 import org.apache.ibatis.exceptions.TooManyResultsException;
 31 import org.apache.ibatis.executor.BatchResult;
 32 import org.apache.ibatis.executor.ErrorContext;
 33 import org.apache.ibatis.executor.Executor;
 34 import org.apache.ibatis.executor.result.DefaultMapResultHandler;
 35 import org.apache.ibatis.executor.result.DefaultResultContext;
 36 import org.apache.ibatis.mapping.MappedStatement;
 37 import org.apache.ibatis.session.Configuration;
 38 import org.apache.ibatis.session.ResultHandler;
 39 import org.apache.ibatis.session.RowBounds;
 40 import org.apache.ibatis.session.SqlSession;
 41 
 42 /**
 43  *
 44  * The default implementation for {@link SqlSession}.
 45  * Note that this class is not Thread-Safe.
 46  *
 47  * @author Clinton Begin
 48  */
 49 public class DefaultSqlSession implements SqlSession {
 50 
 51   private Configuration configuration;
 52   private Executor executor;
 53 
 54   private boolean autoCommit;
 55   private boolean dirty;
 56   private List<Cursor<?>> cursorList;
 57 
 58   public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
 59     this.configuration = configuration;
 60     this.executor = executor;
 61     this.dirty = false;
 62     this.autoCommit = autoCommit;
 63   }
 64 
 65   public DefaultSqlSession(Configuration configuration, Executor executor) {
 66     this(configuration, executor, false);
 67   }
 68 
 69   @Override
 70   public <T> T selectOne(String statement) {
 71     return this.<T>selectOne(statement, null);
 72   }
 73 
 74   @Override
 75   public <T> T selectOne(String statement, Object parameter) {
 76     // Popular vote was to return null on 0 results and throw exception on too many.
 77     List<T> list = this.<T>selectList(statement, parameter);
 78     if (list.size() == 1) {
 79       return list.get(0);
 80     } else if (list.size() > 1) {
 81       throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
 82     } else {
 83       return null;
 84     }
 85   }
 86 
 87   @Override
 88   public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
 89     return this.selectMap(statement, null, mapKey, RowBounds.DEFAULT);
 90   }
 91 
 92   @Override
 93   public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
 94     return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
 95   }
 96 
 97   @Override
 98   public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
 99     final List<? extends V> list = selectList(statement, parameter, rowBounds);
100     final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<K, V>(mapKey,
101         configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
102     final DefaultResultContext<V> context = new DefaultResultContext<V>();
103     for (V o : list) {
104       context.nextResultObject(o);
105       mapResultHandler.handleResult(context);
106     }
107     return mapResultHandler.getMappedResults();
108   }
109 
110   @Override
111   public <T> Cursor<T> selectCursor(String statement) {
112     return selectCursor(statement, null);
113   }
114 
115   @Override
116   public <T> Cursor<T> selectCursor(String statement, Object parameter) {
117     return selectCursor(statement, parameter, RowBounds.DEFAULT);
118   }
119 
120   @Override
121   public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
122     try {
123       MappedStatement ms = configuration.getMappedStatement(statement);
124       Cursor<T> cursor = executor.queryCursor(ms, wrapCollection(parameter), rowBounds);
125       registerCursor(cursor);
126       return cursor;
127     } catch (Exception e) {
128       throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
129     } finally {
130       ErrorContext.instance().reset();
131     }
132   }
133 
134   @Override
135   public <E> List<E> selectList(String statement) {
136     return this.selectList(statement, null);
137   }
138 
139   @Override
140   public <E> List<E> selectList(String statement, Object parameter) {
141     return this.selectList(statement, parameter, RowBounds.DEFAULT);
142   }
143 
144   @Override
145   public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
146     try {
147       MappedStatement ms = configuration.getMappedStatement(statement);
148       return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
149     } catch (Exception e) {
150       throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
151     } finally {
152       ErrorContext.instance().reset();
153     }
154   }
155 
156   @Override
157   public void select(String statement, Object parameter, ResultHandler handler) {
158     select(statement, parameter, RowBounds.DEFAULT, handler);
159   }
160 
161   @Override
162   public void select(String statement, ResultHandler handler) {
163     select(statement, null, RowBounds.DEFAULT, handler);
164   }
165 
166   @Override
167   public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
168     try {
169       MappedStatement ms = configuration.getMappedStatement(statement);
170       executor.query(ms, wrapCollection(parameter), rowBounds, handler);
171     } catch (Exception e) {
172       throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
173     } finally {
174       ErrorContext.instance().reset();
175     }
176   }
177 
178   @Override
179   public int insert(String statement) {
180     return insert(statement, null);
181   }
182 
183   @Override
184   public int insert(String statement, Object parameter) {
185     return update(statement, parameter);
186   }
187 
188   @Override
189   public int update(String statement) {
190     return update(statement, null);
191   }
192 
193   @Override
194   public int update(String statement, Object parameter) {
195     try {
196       dirty = true;
197       MappedStatement ms = configuration.getMappedStatement(statement);
198       return executor.update(ms, wrapCollection(parameter));
199     } catch (Exception e) {
200       throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
201     } finally {
202       ErrorContext.instance().reset();
203     }
204   }
205 
206   @Override
207   public int delete(String statement) {
208     return update(statement, null);
209   }
210 
211   @Override
212   public int delete(String statement, Object parameter) {
213     return update(statement, parameter);
214   }
215 
216   @Override
217   public void commit() {
218     commit(false);
219   }
220 
221   @Override
222   public void commit(boolean force) {
223     try {
224       executor.commit(isCommitOrRollbackRequired(force));
225       dirty = false;
226     } catch (Exception e) {
227       throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + e, e);
228     } finally {
229       ErrorContext.instance().reset();
230     }
231   }
232 
233   @Override
234   public void rollback() {
235     rollback(false);
236   }
237 
238   @Override
239   public void rollback(boolean force) {
240     try {
241       executor.rollback(isCommitOrRollbackRequired(force));
242       dirty = false;
243     } catch (Exception e) {
244       throw ExceptionFactory.wrapException("Error rolling back transaction.  Cause: " + e, e);
245     } finally {
246       ErrorContext.instance().reset();
247     }
248   }
249 
250   @Override
251   public List<BatchResult> flushStatements() {
252     try {
253       return executor.flushStatements();
254     } catch (Exception e) {
255       throw ExceptionFactory.wrapException("Error flushing statements.  Cause: " + e, e);
256     } finally {
257       ErrorContext.instance().reset();
258     }
259   }
260 
261   @Override
262   public void close() {
263     try {
264       executor.close(isCommitOrRollbackRequired(false));
265       closeCursors();
266       dirty = false;
267     } finally {
268       ErrorContext.instance().reset();
269     }
270   }
271 
272   private void closeCursors() {
273     if (cursorList != null && cursorList.size() != 0) {
274       for (Cursor<?> cursor : cursorList) {
275         try {
276           cursor.close();
277         } catch (IOException e) {
278           throw ExceptionFactory.wrapException("Error closing cursor.  Cause: " + e, e);
279         }
280       }
281       cursorList.clear();
282     }
283   }
284 
285   @Override
286   public Configuration getConfiguration() {
287     return configuration;
288   }
289 
290   @Override
291   public <T> T getMapper(Class<T> type) {
292     return configuration.<T>getMapper(type, this);
293   }
294 
295   @Override
296   public Connection getConnection() {
297     try {
298       return executor.getTransaction().getConnection();
299     } catch (SQLException e) {
300       throw ExceptionFactory.wrapException("Error getting a new connection.  Cause: " + e, e);
301     }
302   }
303 
304   @Override
305   public void clearCache() {
306     executor.clearLocalCache();
307   }
308 
309   private <T> void registerCursor(Cursor<T> cursor) {
310     if (cursorList == null) {
311       cursorList = new ArrayList<Cursor<?>>();
312     }
313     cursorList.add(cursor);
314   }
315 
316   private boolean isCommitOrRollbackRequired(boolean force) {
317     return (!autoCommit && dirty) || force;
318   }
319 
320   private Object wrapCollection(final Object object) {
321     if (object instanceof Collection) {
322       StrictMap<Object> map = new StrictMap<Object>();
323       map.put("collection", object);
324       if (object instanceof List) {
325         map.put("list", object);
326       }
327       return map;
328     } else if (object != null && object.getClass().isArray()) {
329       StrictMap<Object> map = new StrictMap<Object>();
330       map.put("array", object);
331       return map;
332     }
333     return object;
334   }
335 
336   public static class StrictMap<V> extends HashMap<String, V> {
337 
338     private static final long serialVersionUID = -5741767162221585340L;
339 
340     @Override
341     public V get(Object key) {
342       if (!super.containsKey(key)) {
343         throw new BindingException("Parameter ‘" + key + "‘ not found. Available parameters are " + this.keySet());
344       }
345       return super.get(key);
346     }
347 
348   }
349 
350 }
View Code

 

mybatis源码解析-解析器模块

MyBatis源码解析-解析器模块1.前言在MyBatis中涉及多个xml文件,解析这些xml文件自然离不开解析器。本文就来分析一下解析器模块。2.准备工作xml常见的解析方式分为以下三种:DOM(DocumentObjectModel)解析方式SAX(SimpleAPIforXML)解析方式StA... 查看详情

mybatis源码解析mybatis源码体系结构

...中的数据全部解析到Configration类中,供API接口层中的SqlSession接口调用,从而在数据处理层实现具体的处理Mybatis有四大核心组件 查看详情

mybatis源码解析-mybatis-spring原理解析

mybatis-spring原理解析? 没有spring使用Mybatis的步骤是1:创建SqlSessionFactoryBuilder2:通过SqlSessionFactoryBuilder创建要给SqlSessionFactory3: 创建SqlSession4:获取Mapper的代理对象5:执行获取结果很多都是重复步骤,可以交给spring去管理? mybatis-spring... 查看详情

mybatis源码解析5---statementhandler解析

StatementHandler解析接口的作用是statement处理器,位于mybatis包的org.apache.ibatis.executor.statement目录下,源码如下:1packageorg.apache.ibatis.executor.statement;23importjava.sql.Connection;4importjava.sql.SQLException;5impo 查看详情

mybatis源码-解析配置文件之解析的流程

1.简介在之前的文章《mybatis初步使用(IDEA的Maven项目,超详细)》中,讲解了mybatis的初步使用,并总结了以下mybatis的执行流程:通过Resources工具类读取mybatis-config.xml,存入Reader;SqlSessionFactoryBuilder使用上一步获得的reader创建SqlSes... 查看详情

mybatis源码解析-搭建调试环境

MyBatis源码解析-搭建调试环境1.相关工具MavenGitJDK1.8IntelliJIDEA2.源码拉取一般来说,我们直接从https://github.com/mybatis/mybatis-3Fork到自己的仓库中,为什么要Fork呢?我们在之后的源码分析中,我们可能会加一些注释,英文翻译一波,... 查看详情

mybatis源码配置文件解析之五:解析mappers标签(解析xml映射文件)

在上篇文章中分析了mybatis解析<mappers>标签,《mybatis源码配置文件解析之五:解析mappers标签 》重点分析了如何解析<mappers>标签中的<package>子标签的过程。mybatis解析<mappers>标签主要完成了两个操作,第一个... 查看详情

mybatis源码解析(代码片段)

MyBatis源码解析MyBatis是一种ORM框架(objectrelationalmapping)ORM也叫对象关系映射,用于实现面向对象编程语言里不同类型系统的数据之间的转换,在没有MyBatis之前,我们用的是JDBC,有了MyBatis之后,就开始... 查看详情

mybatis源码解析(代码片段)

MyBatis源码解析MyBatis是一种ORM框架(objectrelationalmapping)ORM也叫对象关系映射,用于实现面向对象编程语言里不同类型系统的数据之间的转换,在没有MyBatis之前,我们用的是JDBC,有了MyBatis之后,就开始... 查看详情

mybatis源码配置文件解析之五:解析mappers标签(解析class属性)

在上篇文章中分析了mybatis解析mapper标签中的resource、url属性的过程,《mybatis源码配置文件解析之五:解析mappers标签(解析XML映射文件)》。通过分析可以知道在解析这两个属性的时候首先解析的是对应的XML映射文件,然后解析X... 查看详情

mybatis源码解析(代码片段)

根据上篇的代码跟踪mybatis已经ready好SqlSessionFactory了,下面就是我们怎么去通过这个factory去获取sqlSession会话了,继续扒源码;mybatis-spring-2.0.0.jar入口在这里,加载scan扫描:<!--spring与mybatis整合配置,扫描所有dao,指定的映射器... 查看详情

mybatis3源码解析

Mybatis是支持定制化SQL、存储过程和高级映射的持久层框架。主要完成两件事:封装JDBC的操作利用反射完成Java类和SQL之间的转换mybatis的主要目的就是管理执行SQL是参数的输入和输出,编写SQL和结果集的映射是mybatis的主要优点myba... 查看详情

mybatis——源码解析mybatis框架底层的执行原理(代码片段)

...出SqlSeesionFactory对象3.2通过SqlSeesionFactory对象进而创建出SqlSession对象3.3通过SqlSession的getMapper获取到接口代理对象3.4通过mapper接口的代理对象执行CRUD1.前言MyBatis框架大家肯定都用过 查看详情

mybatis——源码解析mybatis框架底层的执行原理(代码片段)

...出SqlSeesionFactory对象3.2通过SqlSeesionFactory对象进而创建出SqlSession对象3.3通过SqlSession的getMapper获取到接口代理对象3.4通过mapper接口的代理对象执行CRUD1.前言MyBatis框架大家肯定都用过 查看详情

《mybatis3源码深度解析》图书简介

一、图书封面二、书籍目录前言4第1篇Mybatis3源码7第1章搭建Mybatis源码环境71.1Mybatis3简介71.2环境准备71.3获取Mybatis源码81.4导入Mybatis源码到IDE101.5HSQLDB数据库简介131.6本章小结16第2章JDBC规范详解172.1JDBCAPI简介172.1.1建立数据源连接182... 查看详情

《mybatis3源码深度解析》图书简介

一、图书封面二、书籍目录前言4第1篇Mybatis3源码7第1章搭建Mybatis源码环境71.1Mybatis3简介71.2环境准备71.3获取Mybatis源码81.4导入Mybatis源码到IDE101.5HSQLDB数据库简介131.6本章小结16第2章JDBC规范详解172.1JDBCAPI简介172.1.1建立数据源连接182... 查看详情

mybatis插件机制源码解析(代码片段)

引言本篇源码解析基于mybatis3.5.8版本。首先需要说明的是,本篇文章不是mybatis插件开发的教程,而是从源码层面分析mybatis是如何支持用户自定义插件开发的。mybatis的插件机制,让其扩展能力大大增加。比如我们项目... 查看详情

mybatis源码解析mybatis解析全局配置文件(代码片段)

MyBatis介绍MyBatis是一个持久层的ORM框架,使用简单,学习成本较低。可以执行自己手写的SQL语句,比较灵活。但是MyBatis的自动化程度不高,移植性也不高,有时从一个数据库迁移到另外一个数据库的时候需要... 查看详情