还是以第一篇博客中给出的例子,根据代码实例来入手分析。
1 static {
2 InputStream inputStream = MybatisTest.class.getClassLoader().getResourceAsStream("mybatis-configuration.xml");
3 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
4 }
5
6 /**
7 * 查询单个记录
8 */
9 @Test
10 public void testSelectOne() {
11 SqlSession session = sqlSessionFactory.openSession();
12 User user = session.selectOne(NAME_SPACE + ".selectUserById", 1);
13 System.out.println(user);
14 session.close();
15 }
如何加载配置文件前面也已经介绍了,通过配置文件产生SqlSessionFactory,追溯源码可以发现其实现是 DefaultSqlSessionFactory。
1 public SqlSessionFactory build(Configuration config) {
2 return new DefaultSqlSessionFactory(config);
3 }
得到 SqlSessionFactory 之后,就可以通过 SqlSessionFactory 去获取 SqlSession 对象。源码如下:
1 @Override
2 public SqlSession openSession() {
3 return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
4 }
5
6
7 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
8 Transaction tx = null;
9 try {
10 //Environment对象封装了配置文件中对于数据源和事务的配置
11 final Environment environment = configuration.getEnvironment();
12 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
13 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
14 //获取Executor对象,用来执行sql语句
15 final Executor executor = configuration.newExecutor(tx, execType);
16 return new DefaultSqlSession(configuration, executor, autoCommit);
17 } catch (Exception e) {
18 closeTransaction(tx); // may have fetched a connection so lets call close()
19 throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
20 } finally {
21 ErrorContext.instance().reset();
22 }
23 }
这里我们重点看一下第 15 行代码:
1 public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
2 executorType = executorType == null ? defaultExecutorType : executorType;
3 executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
4 Executor executor;
5 if (ExecutorType.BATCH == executorType) {
6 executor = new BatchExecutor(this, transaction);
7 } else if (ExecutorType.REUSE == executorType) {
8 executor = new ReuseExecutor(this, transaction);
9 } else {
10 executor = new SimpleExecutor(this, transaction);
11 }
12 if (cacheEnabled) {
13 executor = new CachingExecutor(executor);
14 }
15 executor = (Executor) interceptorChain.pluginAll(executor);
16 return executor;
17 }
根据执行器类型这里有多种不同的执行器Executor。
注意第 12 行代码,如果我们开启了缓存,即 cacheEnabled = true(这里是一级缓存,默认是开启的),第13行代码使用了装饰器模式,在原有的 Executor 上装饰了缓存功能。
第 15 行用于设置插件。
这时候已经得到SqlSession对象了,实际类型是 DefaultSqlSession。接下来我们就可以通过该对象来执行sql语句了。
1、insert 操作
1 /**
2 * 插入一条记录
3 */
4 @Test
5 public void testInsert() {
6 SqlSession session = sqlSessionFactory.openSession();
7 User user = new User(2, "zhangsan", 22);
8 session.insert(NAME_SPACE + ".insertUser", user);
9 session.commit();
10 session.close();
11 }
通过第8行代码,我们进入到 insert 方法:
1 @Override
2 public int insert(String statement, Object parameter) {
3 return update(statement, parameter);
4 }
注意:这里通过 insert 方法,调用的是 update 方法。
1 public int update(String statement, Object parameter) {
2 try {
3 dirty = true;
4 MappedStatement ms = configuration.getMappedStatement(statement);
5 return executor.update(ms, wrapCollection(parameter));
6 } catch (Exception e) {
7 throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
8 } finally {
9 ErrorContext.instance().reset();
10 }
11 }
第4行根据给的statement参数,获取配置的所有如下信息,并将其封装到 MappedStatement 对象中,关于这个对象后面会详细介绍。
1
2
3 insert into
4 user()
5 value(#{id,jdbcType=INTEGER},#{name,jdbcType=VARCHAR},#{age,jdbcType=INTEGER})
6
①、接着我们看第 5 行代码,首先看 wrapCollection(parameter) 方法:
1 private Object wrapCollection(final Object object) {
2 if (object instanceof Collection) {
3 DefaultSqlSession.StrictMap