1.1 ORM简介
ORM(Object Relational Mapping,对象——关系映射)框架的主要功能是根据映射配置文件,完成数据在对象模型与关系模型之间的映射,同时出屏蔽了连接数据库、创建 Statement 对象、执行 SQL、读取 ResultSet、转换 JavaBean、关闭 ResultSet、Statement 对象以及数据库连接等操作。
1.2 常见持久化框架
Hibernate
通过 hbm.xml 映射文件维护 Java 类与数据库表的映射关系。数据库中所有的表都对应一个 Java 类,表中的每一条数据在运行过程中会被映射成相应的 Java 对象。
JPA
Java Persistence API 是EJB 3.0 中持久化部分的规范,但它可以脱离 EJB 的体系单独作为一个持久化规范进行使用。设计上与 Hibernate 相类似。
Spring JDBC
Spring 框架使用模板方式对原生 JDBC 进行的一层封装。
MyBatis
MyBatis 通过映射配置文件或相应注解将 ResultSet 映射为 Java 对象。相较于 Hibernate,MyBatis更加轻量级,可控性也更高。可以直接编写待执行的原生 SQL 语句,比较适合大数据量、高并发等场景。
MyBatis 提供了强大的动态 SQL 功能,可以根据执行时传入的实际参数值接着出完整的、可执行的 SQL 语句。
1.3 MyBatis 示例
mybatis-config.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>
<property name="username" value="root"/>
<property name="id" value="123"/>
</properties>
<!-- 全局配置信息 -->
<settings>
<!-- 使全局的映射器启用或禁用缓存 -->
<setting name="cacheEnabled" value="true"/>
<!-- 允许JDBC 支持自动生成主键 -->
<setting name="useGeneratedKeys" value="true"/>
<!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 指定 MyBatis 所用日志的具体实现 -->
<!-- <setting name="logImpl" value="SLF4J"/>-->
<!-- 使用驼峰命名法转换字段 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- 别名定义 -->
<typeAliases>
<!-- 配置别名信息,在映射配置文件中可以直接使用别名 -->
<typeAlias alias="Blog" type="com.example.Blog"/>
<typeAlias alias="Author" type="com.example.Author"/>
<typeAlias alias="Post" type="com.example.Post"/>
</typeAliases>
<environments default="development">
<environment id="development">
<!-- 事务管理器的类型 -->
<transactionManager type="JDBC"/>
<!-- 数据源的类型,以及数据库连接信息 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射配置文件的位置 -->
<mappers>
<mapper resource="com/example/BlogMapper.xml"/>
</mappers>
</configuration>
BlogMapper.xml
<?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">
<mapper namespace="com.example.BlogMapper">
<!-- 定义映射规则 -->
<resultMap id="detailedBlogResultMap" type="Blog">
<!-- 构造函数映射 -->
<constructor>
<idArg column="blog_id" javaType="int"/>
</constructor>
<!-- 属性映射 -->
<result column="blog_title" property="title"/>
<!-- 对象属性的映射,同时也是一个嵌套映射 -->
<association property="author" resultMap="authorResultMap"/>
<!-- 集合属性的映射,也是一个匿名的嵌套映射 -->
<collection property="posts" ofType="Post">
<id column="post_id" property="id"/>
<result column="post_content" property="content"/>
</collection>
</resultMap>
<resultMap id="authorResultMap" type="Author">
<id column="author_id" property="id"/>
<result column="author_username" property="username"/>
<result column="author_password" property="password"/>
<result column="author_email" property="email"/>
</resultMap>
<!-- 定义查询语句 -->
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
P.id as post_id,
P.blog_id as post_blog_id,
P.content as post_content
from Blog B
left outer join Author A on B.author_id = A.id
left outer join Post P on B.id = P.blog_id
where B.id = #{id}
</select>
</mapper>
Main.java
package com.example;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) throws IOException {
String resource = "com/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 加载 mybatis-config.xml 配置文件,创建 SqlSessionFactory 对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 创建 SqlSession 对象
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
Map<String, Object> parameter = new HashMap<>();
parameter.put("id", 1);
// 执行 select 语句,将 ResultSet 结果集映射成对象并返回
Blog blog = sqlSession.selectOne("com.example.BlogMapper.selectBlogDetails", parameter);
// 输出查询结果
System.out.println(blog);
} finally {
// 关闭 SqlSession 对象
sqlSession.close();
}
}
}
完整代码已同步上传至 gitee
1.4 MyBatis 整体架构
1.4.1 基础支持层
- 反射模块:对 Java 原生的反射进行了良好的封装
- 类型转换模块:1. 别名机制;2. JDBC 类型与 Java 类型之间相互转换
- 日志模块:集成第三方日志框架,如 Log4j、Log4j2、slf4j 等
- 资源加载模块:封装类加载器
- 解析器模块:1. 封装 XPath,2. 处理动态 SQL 的占位符
- 数据源模块:连接池、检测连接状态等
- 事务管理:与 Spring 集成,由 Spring 管理事务
- 缓存模块:提供一级缓存和二级缓存
- Binding模块:将用户自定义的 Mapper 接口与映射配置文件关联起来
1.4.2 核心处理层
-
配置解析,解析 mybatis-config.xml 配置文件、映射配置文件以及 Mapper 接口中的注解信息
-
SQL 解析与 scripting 模块,解析动态 SQL
-
SQL 执行,如图
-
插件
1.4.3 接口层
核心:SqlSession,定义了 MyBatis 暴露给应用程序调用的 API
1.5 本章小结
- ORM 框架的相关概念及价值
- 常用的 ORM 框架
- MyBatis 使用示例
- MyBatis 整体构架