Mybatis全方位剖析【二】——如何使用Mybatis?
一、编程式使用
通过上一节我们了解到了为什么使用MyBatis以及MyBatis能够解决的问题,这一节来看一下MyBatis是如何使用的
1. 引入MyBatis的jar
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
2. 创建一个MyBatis的全局配置文件如MyBatis-config.xml文件,该配置文件是对MyBatis的核心行为的控制,这里只配置了部分信息
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="BlogMapper.xml"/>
</mappers>
</configuration>
数据源配置信息db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true
jdbc.username=root
jdbc.password=root
3. 示例代码
/**
* @Description: MyBatis API方式
* @Author zdp
* @Date 2021-12-08 17:03
*/
@Test
public void testStatement() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
Blog blog = session.selectOne("com.zdp.mapper.BlogMapper.selectBlogById", 1);
System.out.println(blog);
} finally {
session.close();
}
}
4. 控制台打印输出
以上就是MyBatis的API编程式简单使用,这样的调用方式,解决了重复代码、资源管理、SQL管理、结果集映射的问题,但是这种方式中Statement Id 是硬编码,维护起来不方便,不能在编译时就进行类型检查,如果NameSpace 或者Statement Id 写错了,只有在运行时才会报错。通常我们会使用第二种方式,也是新版MyBatis里面推荐的方式:定义一个Mapper接口的方式。这 个接口全路径必须跟 Mapper.xml 里面的 NameSpace 对应起来,方法也要跟 Statement Id相对应。
/**
* @Description: 通过 SqlSession.getMapper(XXXMapper.class) 接口方式
* @Author zdp
* @Date 2021-12-08 17:03
*/
@Test
public void testMybatis() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlogById(1);
System.out.println(blog);
} finally {
session.close();
}
}
二、核心对象的生命周期
从上面的示例Demo中可以看到MyBatis 里面的几个核心对象:SqlSessionFactoryBuiler、SqlSessionFactory、SqlSession 和 Mapper 对象。如果说我们不用容器,自己去管理这些对象的话,我们必须思考一个问题:什么时候创建和销毁这些对象?
1. SqlSessionFactoryBuiler
SqlSessionFactoryBuiler 。 它 是 用 来 构 建 SqlSessionFactory 的 , 而SqlSessionFactory 只需要一个,所以只要构建了这一个 SqlSessionFactory,也就没有存在的意义了。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)
2. SqlSessionFactory
SqlSessionFactory 是用来创建 SqlSession 的,每次应用程序访问数据库,都需要创建一个会话。因为我们一直有创建会话的需要,所以 SqlSessionFactory应该存在于应用的整个生命周期中(作用域是应用作用域)。创建SqlSession 只需要一个实例来做这件事就行了,否则会产生很多的混乱,和浪费资源。所以我们要采用单例模式
3. SqlSession
SqlSession 是一个会话,因为它不是线程安全的,不能在线程间共享。所以我们在 请求开始的时候创建一个SqlSession对象,在请求结束或者说方法执行完毕的时候要及时关闭它(一次请求或者操作中)
4. Mapper
Mapper(实际上是一个代理对象)是从SqlSession 中获取的。它的作用是发送 SQL来操作数据库的数据。它应该在一个SqlSession 事务方法之内。
三、MyBatis核心配置剖析
我们在使用MyBatis时,通常使用很少的配置就可以让MyBatis运行起来,像上面的示例Demo中,只配置了数据源。在MyBatis里面提供了非常多的配置项,我们没有在MyBatis配置文件中配置的时候,都是使用的系统的默认值,接下来看一下这些核心配置文件中的标签,在MyBatis官网中其实已经有非常详细的介绍,这里列举其中几个标签。
1. configuration
configuration 是整个配置文件的根标签,实际上也对应着 MyBatis 里面最重要的配置类 Configuration
2. properties
properties标签用来配置参数信息,比如最常见的数据库连接信息,为了避免直接把参数写死在 xml 配置文件中,我们可以把这些参数单独放在 properties 文件中,用 properties 标签引入进来,然后在 xml 配置文件中用${}引用就可以了。
3. typeAliases
TypeAlias 是类型的别名,跟 Linux 系统里面的 alias 一样,主要用来简化全路径类名的拼写。比如我们的参数类型和返回值类型都可能会用到我们的Bean,如果每个地方都配置全路径的话,那么内容就比较多,还可能会写错。 我们可以为自己Bean创建别名,既可以指定单个类,也可以指定一个 package, 自动转换。配置了别名以后,只需要写别名就可以了,比如 com.zdp.entity.Blog 都只要写 blog 就可以了。 在MyBatis 里面有系统预先定义好的类型别名,在 TypeAliasRegistry 中。
4. typeHandlers
由于 Java 类型和数据库的 JDBC 类型不是一一对应的(比如 String 与 varchar), 所以我们把 Java 对象转换为数据库的值,和把数据库的值转换成 Java 对象,需要经一定的转换,这两个方向的转换就要用到 TypeHandler。在MyBatis中已经内置了很多TypeHandler,它们都注册在TypeHandlerResistry中。不清楚的可以看看这个typeHandlers详解
5. objectFactory
当我们把数据库返回的结果集转换为实体类的时候,需要创建对象的实例,由于我们不知道需要处理的类型是什么,有哪些属性,所以不能用 new 的方式去创建。在 MyBatis 里面,提供了一个工厂类的接口,叫做 ObjectFactory,专门用来创建对象的实例,里面定义了4个方法:
方法 | 作用 |
---|---|
void setProperties(Properties properties); | 设置参数时调用 |
T create(Class type); | 创建对象(调用无参构造函数) |
T create(Class type, List<Class<?>> constructorArgTypes, List constructorArgs); | 创建对象(调用带参数构造函数) |
boolean isCollection(Class type) | 判断是否集合 |
ObjectFactory 有一个默认的实现类 DefaultObjectFactory,创建对象的方法最终都调用了 instantiateClass(),是通过反射来实现的。 如果想要修改对象工厂在初始化实体类的时候的行为,就可以通过创建自己的对象工厂,继承 DefaultObjectFactory 来实现(不需要再实现 ObjectFactory 接口)不清楚的可以看看这个objectFactory解析
6. plugins
插件是 MyBatis 的一个很强大的机制,跟很多其他的框架一样,MyBatis 预留了插件的接口,让MyBatis 更容易扩展。根据官方的定义,插件可以拦截这四个对象的这些方法,我们把这四个对象称作 MyBatis 的四大对象
类(或接口) | 方法 |
---|---|
Executor | update, query, flushStatements, commit, rollback, getTransaction, close, isClosed |
ParameterHandler | getParameterObject, setParameters |
ResultSetHandler | handleResultSets, handleOutputParameters |
StatementHandler | prepare, parameterize, batch, update, query |
通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。
7. mappers
标签配置的是我们的映射器,也就是 Mapper.xml 的路径。这里配置的目的是让 MyBatis 在启动的时候去扫描这些映射器,创建映射关系。我们有四种指定 Mapper 文件的方式:
1、使用相对于类路径的资源引用(resource)
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
2、使用完全限定资源定位符(绝对路径)(URL)
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
3、使用映射器接口实现类的完全限定类名
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
4、将包内的映射器接口实现全部注册为映射器
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
四、Mapper.xml 映射配置文件
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
cache – 该命名空间的缓存配置。
cache-ref – 引用其它命名空间的缓存配置。
resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
sql – 可被其它语句引用的可重用语句块。
insert – 映射插入语句。
update – 映射更新语句。
delete – 映射删除语句。
select – 映射查询语句。
1. select
select元素使用及详细解析
2. insert
insert元素使用及详细解析
//TODO
3. update
update 元素使用及详细解析
//TODO
4. delete
delete元素使用及详细解析
//TODO