大部分时候,我们都是在Spring里面去集成MyBatis。因为Spring对MyBatis的一些操作进行的封装,我们不能直接看到它的本质,所以先看下不使用容器的时候,也就是编程的方式,MyBatis怎么使用
1)依赖:导入 mybatis 的 jar包。
2)配置文件:全局配置文件,这里面是对 MyBatis 的核心行为的控制。我们常命名为 mybatis-config.xml。
3)映射器文件:通常来说一张表对应一个,我们会在这个里面配置我们增删改查的SQL语句,以及参数和返回的结果集的映射关系。我们常命名为 ~mapper.xml。一共有8个标签:
1. <cache> – 给定命名空间的缓存配置(是否开启二级缓存)。
2. <cache-ref> – 其他命名空间缓存配置的引用。
3. <resultMap> – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
<resultMap id="BaseResultMap" type="Employee">
<id column="emp_id" jdbcType="INTEGER" property="empId"/>
<result column="emp_name" jdbcType="VARCHAR" property="empName"/>
<result column="gender" jdbcType="CHAR" property="gender"/>
<result column="email" jdbcType="VARCHAR" property="email"/>
<result column="d_id" jdbcType="INTEGER" property="dId"/>
</resultMap>
4. <sql> – 可被其他语句引用的可重用语句块。
<sql id="Base_Column_List">
emp_id, emp_name, gender, email, d_id
</sql>
5. <insert> – 映射插入语句
6. <update> – 映射更新语句
7. <delete> – 映射删除语句
8. <select> – 映射查询语句
4)Java代码:具体执行 Mapper.xml 中的 sql 语句,跟 JDBC 的代码一样,我们要执行对数据库的操作,必须创建一个会话,这个在MyBatis里面就是SqlSession,SqlSession是工厂类根据全局配置文件创建的。
编码方式一
获取执行sql后执行,通过 statementId(实际就是sqlid,但一般要加上namespace才能唯一确定)直接获取相应sql,然后通过sqlSession相应方法执行。这种方式有一个明显的缺点,就是会对StatementID硬编码,而且不能在编译时进行类型检查
public void testMapper() throws IOException {
// 全局配置文件(在resource目录下)
String resource = "mybatis-config.xml";
InputStream inputStream = Resources. getResourceAsStream(resource);
// 1.SqlSessionFatoryBuilder,根据全局配置文件创建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
// 2.SqlSessionFactory,在SQLSessionFactory中拿到一个SqlSession
SqlSession session = sqlSessionFactory.openSession();
try {
// 3.SqlSession,通过statementId(nameSpace+id)找到具体sql,通过SqlSession方法执行
// 注:1.这种硬编码方式,可以给mapper.xml的namespace任意命名
// 2.selectOne 是 SqlSession 的方法(另外还有insert,delete),实际调用的是执行器 Executor 的 doQuery()
// 3.若是增删改,最后要提交 session.commit()
Blog blog = session.selectOne("blog.findUserById",1);
System.out.println(blog);
} finally {
// 4.关闭当前会话(连接)SqlSesion
session.close();
}
}
关于全局配置文件 mybatis-conf.xml 可以参考这篇文章…
编码方式二(常用)
Mapper代理模式。通过接口来代理一个 mapper.xml 的执行,这个接口全路径必须跟 Mapper.xml 里面的 namespace 对应起来,方法也要跟 StatementID一一对应。
public interface BlogMapper {
Blog selectBlogById(int id);
}
public void testMapper() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources. getResourceAsStream(resource);
// 1.SqlSessionFatoryBuilder,根据全局配置文件创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
// 2.SqlSessionFatory,在SQLSessionFactory中拿到一个SqlSession
SqlSession session = sqlSessionFactory.openSession();
try {
// 3.SqlSession,通过接口类拿到相应Mapper
// 注:1.mapper.xml的namespace=接口相对路径
// 2.mapper.xml的statementId=接口方法名
BlogMapper mapper = session.getMapper(BlogMapper.class);
// 4.Mapper,通过Mapper调用mapper.xml中的sql
// 相当于上面硬编码一行代码做的事,这里需要两行
Blog blog = mapper.selectBlogById(1);
System.out.println(blog);
} finally {
// 5.关闭当前会话(连接)SqlSesion
session.close();
}
}
核心对象生命周期
在编程式使用的这个 demo 里面,我们看到了 MyBatis 里面的几个核心对象:SqlSessionFactoryBuiler、SqlSessionFactory、SqlSession 和 Mapper 对象。这几个核心对象在MyBatis的整个工作流程里面的不同环节发挥作用。
注:对于我们编码上述四个对象是核心对象,而对于 MyBatis 真正执行一条 Sql 语句时,核心对象是 Executor、StatementHandler、ParameterHandler、ResultSetHandler。
如果说我们不用容器,自己去管理这些对象的话,我们必须思考一个问题:什么时候创建和销毁这些对象?
在一些分布式的应用里面,多线程高并发的场景中,如果要写出高效的代码,必须了解这四个对象的生命周期。这四个对象的生命周期的描述在官网上面也可以找到。
-
SqlSessionFactoryBuiler
首先是 SqlSessionFactoryBuiler。它是用来构建 SqlSessionFactory 的,而 SqlSessionFactory 只需要一个,所以只要构建了这一个 SqlSessionFactory,它的使命就完成了,也就没有存在的意义了。所以它的生命周期只存在于方法的局部。
-
SqlSessionFactory
SqlSessionFactory是用来创建SqlSession的。因为每次应用程序访问数据库,都需要创建一个会话,所以我们一直有创建会话的需要,所以 SqlSessionFactory 应该存在于应用的整个生命周期中(作用域是应用作用域)。创建SqlSession只需要一个实例来做这件事就行了,否则会产生很多的混乱,和浪费资源。所以我们要采用单例模式。
-
SqlSession
SqlSession是一个会话,因为它不是线程安全的,不能在线程间共享。所以我们在请求开始的时候创建一个SqlSession对象,在请求结束或者说方法执行完毕的时候要及时关闭它(存在于一次请求或者操作中)。 另外可以将SqlSession设计成线程唯一(如通过ThreadLocal) -
Mapper
Mapper(实际上是一个代理对象)是从SqlSession中获取的。 它的作用是发送 SQL来操作数据库的数据。它应该在一个 SqlSession 事务方法之内。BlogMapper mapper = session.getMapper(BlogMapper.class);
总结一下:
| 对象 | 生命周期 |
|---|---|
| SqlSessionFactoryBuilder | 方法局部(method) |
| SqlSessionFactory | 应用级别(Application) |
| SqlSession | 请求和操作(Request/method) |
| Mapper | 方法(method) |






还没有评论,来说两句吧...