MyBatis介绍
MyBatis框架弥补了传统JDBC开发模式的不足,同时其强大的加载配置、SQL解析与执行、结果映射等机制使得项目的开发效率和程序的数据处理性能得到大大的提升。
MyBatis可以将SQL语句配置在XML文件中,这避免了JDBC在Java类中添加SQL语句的硬编码问题;通过MyBatis提供的输入参数映射方式,将参数自由灵活地配置在SQL语句配置文件中,解决了JDBC中参数的手工配置问题;通过MyBatis的输出映射机制,将结果集的检索自动映射成相应的Java对象,避免了JDBC中对结果集手工检索;同时MyBatis还可以创建自己的数据库连接池,使用XML配置文件的形式,对数据库连接数据进行管理,避免了JDBC的数据库连接参数的硬编码问题。
总之,MyBatis的特点是采用配置文件动态管理SQL语句,并包含有输入映射、输出映射机制以及数据库连接池配置的持久化框架。
MyBatis整体架构
MyBatis整体的构造由数据源配置文件、SQL映射配置文件、会话工厂、会话、执行器以及底层封装的对象组成。
1.数据源配置文件
对于一个持久化框架,也就是负责连接数据库,并对数据进行操作的一套框架,连接数据库是最重要的一步。MyBatis框架对于数据库连接的配置信息,采用了配置“数据库连接池”(又可称“数据源”),就是让数据库的配置信息从外部的某配置文件中读取,然后由一个独立处理数据库连接的程序来和数据库进行交互。
在MyBatis中,数据库的数据源是配置在SqlMapConfig.xml(文件名可更改)配置文件中,其中配置了数据库驱动、数据库连接地址、数据库用户名密码、事务管理等参数,如果对数据库连接池的性能有要求,还可以配置连接池的连接数和空闲时间等详细参数。
<?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属性:
用于指定配置文件的位置, 是按照类路径的写法来写, 并且必须存在于类路径下
url属性:
URL: Uniform Resource Locator 统一资源定位符
http://localhost:8080/mystroe/CategoryServlet URL
协议 主机 端口
URI:Uniform Resource Identifier 统一资源标识符
/mystroe/CategoryServlet
它是可以在web应用中唯一定位一个资源的路径
-->
<properties resource="jdbcConfig.properties"></properties>
<!--配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 配置映射文件的位置 -->
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
2.SQL映射配置文件
传统的JDBC开发模式中,SQL语句的硬编码在Java代码中。而MyBatis框架,将SQL配置在独立的配置文件Mapper.xml(文件名可更改)中,简称Mapper配置文件。在这个配置文件中可以配置任何类型的SQL语句,包括select、update、delete、insert语句,对于SQL语句的执行所需要的参数,以及查询语句返回的结果集对象,都可以在Mapper配置文件中配置。
在输入参数方面,MyBatis框架会根据配置文件中的参数配置,将组装参数的Java对象或Map对象中的相关字段与Mapper.xml中的参数配置做匹配,将相关的数据绑定在需要执行的SQL语句上;在查询语句输出结果时,会根据Mapper.xml中的配置的结果集信息,将从数据库字段取出的数据字段,一一映射到相对应的Java对象或Map对象中。
Mapper.xml文件路径一般会配置在SqlMapConfig.xml中,Mapper文件大致内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 -->
<mapper namespace="test">
<!-- id:statement的id 或者叫做sql的id-->
<!-- parameterType:声明输入参数的类型 -->
<!-- resultType:声明输出结果的类型,应该填写pojo的全路径 -->
<!-- #{}:输入参数的占位符,相当于jdbc的? -->
<!-- 通过id查询一个用户 -->
<select id="findUserById" parameterType="integer" resultType="com.itheima.domain.User">
select * from user where id=#{id};
</select>
<!-- 通过username 模糊查询用户列表
#{}: 占位符
${}:字符串拼接
-->
<select id="findUserByUsername" parameterType="String" resultType="com.itheima.domain.User">
select * from user where username like '%${value}%';
</select>
<!-- 添加用户 -->
<insert id="insertUser" parameterType="com.itheima.domain.User">
INSERT INTO user (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address});
</insert>
<!-- 更新用户 -->
<update id="updatetUser" parameterType="com.itheima.domain.User" >
update user set username=#{username} where id=#{id};
</update>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="integer">
delete from user where id= #{id};
</delete>
</mapper>
注:parameterType指定了输入参数的类型,而resultType指定了输出结果映射的Java对象的类型。可以看到其中的resultType的参数信息是一个JavaBean,即这条select的结果参数配置表示将单条记录映射成一个Java对象。
3.会话工厂和会话
MyBatis 之会话 Session 执行逻辑
1.SQL 会话工厂构建器类 SqlSessionFactoryBuilder 的 build 方法用于构建 SqlSessionFactory 类的实例;
2.SQL 会话工厂类的实例SqlSessionFactory 用于创建 Sql 会话 SqlSession 的实例;
3.SQL 会话 SqlSession 用于执行具体的 CURD 操作,其类似于 JDBC 中的连接类 Connection;
4.SQL 会话模板 SqlSessionTemplate 是 MyBatis 为 Spring 提供的模板化的会话工具,是线程安全的,可以通过构造器或 setter 方法注入 SqlSessionFactory 类的实例;
public static void main(String[] args) {
String resource = "config/mybatis-config.xml";
InputStream inputStream;
SqlSession session = null;
try {
inputStream = Resources.getResourceAsStream(resource);
// 构建sqlSession工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取sqlSession
session = sqlSessionFactory.openSession();
// 方法1(使用构建工厂的方式获取)
String statement = "com.mapper.ISupplierMapper.getSupplierNameList";
List<Supplier> student = session.selectList(statement);
System.out.println(student);
// 方法2(使用构建工厂的方式获取)
SupplierMapper supplierMapper = session.getMapper(SupplierMapper.class);
List<Supplier> list = supplierMapper.getSupplierNameList();
System.out.println(list);
// SqlSessionManager方式,通过SqlSessionManager自己维护的一个ThreadLocal,实现session的复用(线程安全)
SqlSessionManager sessionManager = SqlSessionManager.newInstance(inputStream);
sessionManager.startManagedSession();
List<Supplier> list2 = sessionManager.selectList(statement);
} catch (IOException e) {
e.printStackTrace();
} finally {
session.close();
}
}
4.MyBatis运行流程
首先SqlSessionFactory 会话工厂会通过Resources资源信息加载对象获取SqlMapConfig.xml配置文件信息,然后产生可以和数据库进行交互的会话实例类sqlSession。会话实例类SqlSession可以根据Mapper配置文件中的SQL配置,去执行相应的增删改查操作。而在SqlSession类内部,是通过执行器Executor(分为基本执行器和缓存执行器)对数据库进行操作的。执行器Executor与数据库交互,依靠的是底层封装对象的Mapper Statement,它封装了从Mapper文件中读取信息(包括SQL语句、输入参数、输出结果类型)。通过执行器Executor与底层封装对象Mappered Statement的结合,Mybatis就实现了与数据库进行交互的功能。
5.MyBatis主要构件及其相互关系
SqlSession:作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能;
Executor:MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护;
StatementHandler:封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。
ParameterHandler:负责对用户传递的参数转换成JDBC Statement 所需要的参数;
ResultSetHandler:负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;
TypeHandler:负责java数据类型和jdbc数据类型之间的映射和转换;
MappedStatement:MappedStatement维护了一条<select|update|delete|insert>节点的封装;
SqlSource:负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回;
BoundSql:表示动态生成的SQL语句以及相应的参数信息;
Configuration:MyBatis所有的配置信息都维持在Configuration对象之中;