本文通过 main() 方法来用 mybatis 执行带参数的 SQL 命令,来介绍 mybatis 执行 SQL 的大致过程。
准备数据库
准备一个 MySQL 数据库,十分钟内快速运行起一个 MySQL 的方法可以看这篇文章。
数据库内创建一张很简单的表:
create database test;
use test;
create table t1(int id);
insert into t1 set id=11;
创建项目
首先创建一个空的 Maven 项目,加上下面的依赖关系:
<dependencies>
<!-- mybatis 本身 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<!-- 连接池数据源 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.5.0</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!-- 日志输出 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
创建 main() 方法
在项目中随便创建一个类,写一个空的 main()
方法,确认这个方法可以正常运行。
接下来我们在 main()
方法中,一步一步完成这个使用 mybatis 执行 SQL 命令的例子。
1. 初始化数据源
要连接数据库,自然要先准备好数据源对象,这里就不多做解释了:
String url = "jdbc:mysql://localhost/test?serverTimezone=UTC";
String username = "root";
String password = "root123";
org.apache.commons.dbcp2.BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource
变量就是准备好的数据源对象。
2. 定义要执行的 SQL 命令
SqlCommandType commandType = SqlCommandType.SELECT;
String commandId = "sql1";
String commandStatement = "select * from t1 where id=#{id}";
String parameterName = "id";
Class<?> parameterType = Integer.class;
Object parameterValue = 11;
Class<?> resultType = HashMap.class;
List<ResultMapping> resultPropertyMappings = Collections.emptyList();
这个定义分为三部分:
- 一是命令本身,包括命令的类型、ID、语句。在 mybatis 中,每条 SQL 命令都有唯一的 ID,因为在 SqlSession 里面,执行哪条 SQL 命令就是通过 ID 来指定的。
- 二是参数,包括参数的名称、类型、参数值。这个例子中只有一个参数,参数名称
id
和语句里面的#{id}
名称必须保持一致。 - 三是返回值的类型。返回值的类型包括两部分,一是返回结果本身的类型,二是返回结果的每个字段各是什么类型(用于转换)。这个例子当中,我们简单的将返回结果包装为 Map 对象,所以里面的字段值就不去指定类型转换了,即
resultPropertyMappings
变量是个空的 List。
上面这 8 个变量,会在组装 mybatis 的 SQL 命令过程中用到。
3. 初始化 mybatis 配置
mybatis 的所有配置都在 org.apache.ibatis.session.Configuration
对象当中。Configuration
对象是一个很复杂的对象,涵盖了执行 SQL 命令需要的所有东西。正常使用的情况下,我们要为它配置 XML 路径、Mapper 所在的包、查询结果的类型转换等等。在本文的例子当中,我们用不到 XML,所以只做最简单的配置:
JdbcTransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("default", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
可以看出,dataSource
变量是先放入 Environment
对象,然后再放入 Configuration
对象的。到这里,mybatis 的数据源就配置好了。接下来我们将之前定义的 SQL 命令加入 mybatis。
4. 构建 MappedStatement
mybatis 当中所有的 SQL 命令最终都是一个 MappedStatement
对象。但要构建它可不简单,我们要把前面定义的 SQL 命令三部分分别构建相应的对象,然后再组装成 MappedStatement
对象。
// 1. 构建 SqlSource 对象
SqlSource sqlSource = new SqlSourceBuilder(
configuration
).parse(
commandStatement, parameterType, null
);
// 2. 构建 ResultMap 对象
String resultMapId = commandId + "-Inline";
ResultMap resultMap = new ResultMap.Builder(
configuration, resultMapId, resultType, resultPropertyMappings, null
).build();
// 3. 构建 ParameterMap 对象
ParameterMap parameterMap = new ParameterMap.Builder(
configuration, commandId, null,
Collections.singletonList(
new ParameterMapping.Builder(
configuration, parameterName, Integer.class
).build()
)
).build();
// 4. 将 SqlSource 对象、 ResultMap 对象和 ParameterMap 对象
// 组合成最终的 MappedStatement 对象
MappedStatement mappedStatement = new MappedStatement.Builder(
configuration, commandId, sqlSource, commandType
).resultMaps(
Collections.singletonList(resultMap)
).parameterMap(
parameterMap
).build();
看得出,因为构建起来很复杂,所以 mybatis 定义了大量 Builder 类来用。
5. 将 MappedStatement 加入 mybatis
configuration.addMappedStatement(mappedStatement);
所有的 MappedStatement
都要放入 Configuration
。
6. 初始化 SqlSession 并执行 SQL 命令
这一步相信熟悉 mybatis 的同学都会用,就不多解释了。
SqlSessionFactory sqlSessionFactory = new DefaultSqlSessionFactory(configuration);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
List<Object> result = sqlSession.selectList(commandId, parameterValue);
System.out.println(result);
上面这六个片段依次加入 main()
方法,即可完整执行。这就是 mybatis 执行 SQL 命令的基本套路。
有的同学就会问,那我在 XML 里面定义的 SQL 语句是怎么解析执行的呢?mybatis 有个叫 org.apache.ibatis.scripting.LanguageDriver
的接口类,负责将 XML 或其他语言的动态 SQL 模板解析为最终的 SQL 语句,然后交给 SqlSourceBuilder
生成 SqlSource
对象。具体可以看看源码。相信理解了本文之后再去看 mybatis 的源码,会对它的执行机制有更清晰的了解。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。