MyBatis的基本构成
简单的了解一下MyBatis的核心组件,对于接下来理解MyBatis的执行过程更容易理解
- SqlSessionFactoryBuilder (工厂构造器) 它会根据配置信息或者代码来生成SqlSessionFactory (工厂接口)。
- SqlSessionFactory (工厂接口) 依靠工厂来生产Session(会话)。
- SqlSession (会话),是一个既可以执行SQL语句并返回结果集,也可以获取Mapper的接口。
- SQL Mapper 是由一个Java接口和XML文件组成(或注解)构成的,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果
关联关系如下图
1.各组件的创建
1.1 构建SqlSessionFactory
每个MyBatis应用都是以SqlSessionFarctory的实例为中心的。
SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得。
SqlSessionFactory是一个工厂接口并非实现类,MyBatis提供了两种实现,
1.DefaultSqlSessionFactory,MyBatis目前使用的该类
2.SqlSessionManaher ,该类目前还没有使用
MyBatis提供了两种模式来创建SqlSessionFactory
一种是XML配置的方式,推荐使用;还有一种就是代码的方式。
在能使用配置文件的情况下,尽量使用配置文件,这样一方面可以减少硬编码,另一方面方便日后维护人员的修改,避免重新编写代码。
以下为SqlSessionFactory关系图
1.1.1使用 XML方式构建
这里配置一个简单 mybatis-config.xml
内部定义 数据源(DataSource)、映射器(SQL Mapper)、别名(Alias)
<?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">
<!--通过这个配置文件,完成mybatis与数据库的连接 -->
<configuration>
<!-- 注意此配置文件内的元素的 -->
<!-- 引入database.properties文件 -->
<properties resource="database.properties"/>
<!--配置mybatis的log实现为LOG4J -->
<!-- 配置后,后台就会有sql语句的输出 -->
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<!-- 设置类的别名 -->
<typeAliases>
<!-- <typeAlias alias="User" type="com.wu.pojo.User"/> -->
<!-- 根据包取别名,把包下面的所有类都按类名来取别名 -->
<!-- 这用可以简化代码量 -->
<package name="com.wu.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<!-- 配置事务管理 ,采用JDBC管理事务-->
<transactionManager type="JDBC"/>
<!-- POOLED是mybatis的 数据源 -->
<!-- JNDI是基于tomcat的数据源 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!-- pojo的映射文件UserMapper引入到配入到配置文件中 -->
<mappers>
<!-- resource要写成路径 -->
<mapper resource="com/wu/dao/UserMapper.xml"/>
<mapper resource="com/wu/dao/RoleMapper.xml"/>
<package name=""/><!-- ???用处??? -->
</mappers>
</configuration>
然后就是通过代码来生成SqlSessionFartory
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory = null;
public static SqlSessionFactory getSqlSessionFactory(){
InputStream inputStream = null;
if(sqlSessionFactory == null){
try {
String resurse = "mybatis-config.xml";
inputStream = Resources.getResourceAsStream(resurse);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
return sqlSessionFactory;
}
}
1.1.2 使用代码生成
其实,通过上面的XML文件,我们可以发现所有参数的封装在 configuration中,那么我们可以大致猜到,MyBatis中有一个Configuration的类,MyBatis会将XML中的配置解析成Configuration对象交由SplSessionFactoryBuild 来生成SqlSessionFactory
Configuration该类存在于org.apache.ibatis.session.Configuration
而SqlSessionFactoryBuilder也提供了以下方法来创建
显而易见,如果我们用代码生成SqlSessionFactory,其实是手动创建Configuration对象,将数据库信息和各种配置信息填入即可。
一般情况下,不建议使用这种方法来创建SqlSeesionFactory.
1.2 创建SqlSession
SqlSession是个接口类,扮演着门面的作用,而真正干活的是Executor接口;
可以认为是一个委派模式吧。暂时我们不深入讨论Executor接口。
我们可以看到SqlSessionFactory中提供了众多方法用于创建SqlSession,
暂时不去深究每个方法生产的SqlSession各有什么不同。
当然SqlSession类似于JDBC中的Connection,所以也需要在finally中将其关闭
//定义SqlSession
SqlSession sqlSession = null;
try {
//创建 SqlSession
sqlSession = sqlSessionFactory.openSession();
//运行sql
。。。。
//提交事务
sqlSession.commit();
} catch (Exception e){
e.printStackTrace();
} finally {
//关闭 SqlSession
if (sqlSession != null) {
sqlSession.close();
}
}
SqlSession是个接口的实现类有两个,分别是DefaultSqlSession和SqlSessionManager,
SqlSession的用途主要有两种。
(1).获取SQL Mapper 映射器,让映射器通过命名空间和方法名称找到对应的SQL,发送给数据库执行后返回结果;
(2).直接通过命名信息去执行SQL,通过XML映射文件中的配置的SQL的id来操作,同时SqlSession也支持事务,commit,rollback方法来提交和回滚事务。
1.3 映射器(SQL Mapper)
映射器是由 Java接口和XML文件(或注解)共同组成的,
它的作用如下:
a.定义参数类型
b.描述缓存
c.描述SQL语句
d.定义结果集和对象间的映射关系
映射器的实现:
映射器的实现有两种方式
一种是通过XML文件形式实现,然后在mybatis-config.xml文件中扫描XML来生成映射器
还有一种是通过注解去实现
在此强烈推荐XML方式实现,原因如下:
Java注解是受限的,功能有限,而mybatis的Mapper内容相当多,而且相当复杂,功能强大,使用XML文件方式可以带来更为灵活的空间;
如果SQL过于复杂,多关联,多条件,尤其是动态SQL的时候,写在Java文件中可读性差,增加了维护成本。
2.生命周期
在web应用,连接池等多线程场景下,生命周期显得尤为重要,如果不了解生命周期可能带来很严重的并发问题或者资源占用,了解其生命周期对于MyBatis应用的正确性和高效性是极其重要的。
2.1 SqlSessionFactory
SqlSessionFactory的作用是创建SqlSession,而SqlSession相当于会话,相当于JDBC中的Connection对象。每次应用程序需要访问数据库,都需要通过SqlSessionFactory来创建 SqlSession,
所以SqlSessionFactory应该是MyBatis应用全局。
因为多次创建同一个数据源的SqlSessionFactory,就会打开多余的连接资源,那么连接资源很快就会被耗尽,因此SqlSessionFactory的责任的唯一的,所以SqlSessionFactory是全局唯一的单例,每个数据源对应一个唯一的SqlSessionFactry。
2.2 SqlSession
SqlSession相当于Connection对象,那么它的生命周期就应该是事务级别的。
因为SqlSession的个线程不安全的对象,在涉及多线程的时候我们需要特别当心,操作数据库需要注意其隔离级别,数据库锁等高级特性。此外每次创建的SqlSession都必须及时关闭,它长期存在就会导致数据库连接资源被占用,导致活动资源减少,对系统性能影响很大。通常在fianlly语句块中将其关闭SqlSession。
它存活在一个应用的请求和操作中,可以执行多条SQL,保证事务的一致性,
2.3 Mapper
Mapper是一个接口,作用就是发送SQL并返回结果集,或者执行新增删除操作,因此它应该在一个SqlSession事务方法之内,是一个方法级别的东西,当时也有情况不同,当spring集成MyBatis时,spring会将Mapper扫描成bean对象,从而成为全局性的对象,这一块内容留到spring中讲解