Chapter 1. 框架概述

1.1 三层架构

三层架构所包含的三层:

  • 界面层(User Interface Layer):主要功能为接收用户的数据,显示请求的处理结果。
  • 业务逻辑层(Business Logic Layer):接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。
  • 数据访问层(Data Access Layer):与数据库打交道,主要实现对数据的增、删、改、查。将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库。

处理请求的交互:

用户->界面层->业务逻辑层->数据访问层->DB数据库

1.2 框架定义

框架(Framework),是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法。另一种认为,框架可被应用开发者定制的应用骨架、模板。

简单的说,框架其实是半成品软件,就是一组组件,供你使用完成你自己的系统。但它是安全的,可复用的,不断升级的软件。

1.3 常用框架

  • MyBatis 框架:基于 Java 的持久层框架,内部封装了 JDBC。它通过 XML 或 注解 两种方式将需执行的 SQL 语句配置起来,并通过 Java 对象和 SQL 的动态参数进行映射生成最终执行的 SQL 语句,最后再由 MyBatis 框架执行 SQL 并将结果映射到 Java 对象并返回
  • Spring 框架:解决业务对象与功能模块之间的耦合。Spring 是一个轻量级控制反转(IOC)和面向切面(AOP)的容器。
  • Spring MVC 框架:为 Spring 框架提供了构建 Web 应用程序的能力。

Chapter 2. MyBatis 概述

2.1 MyBatis 简介

MyBatis 是一个优秀的基于 Java 的持久层框架,内部封装了 JDBC,开发者只需要关注 SQL 语句本身,而 MyBatis 已经代替开发者完成了这些任务:

  1. 注册数据库的驱动,如:

    1
    Class.forName("com.mysql.jdbc.Driver")
  2. 创建 JDBC 中必须使用的 ConnectionStatementResultSet 对象。

  3. 从 XML 中获取 SQL 并执行 SQL 语句,将 ResultSet 结果转换为 Java 对象

  4. 关闭资源,如:

    1
    2
    3
    ResultSet.close();
    Statement.close();
    Connection.close();

2.2 快速入门

2.2.1 创建 MySQL 数据库的表(略)

image-20210308162016315

2.2.2 创建 Maven 工程

首先创建 Maven 空项目,再新建 Module,填写好坐标(gav)

image-20210308162451286

2.2.3 添加依赖

pom.xml 中加入 MySQL、MyBatis 的坐标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependencies>
...
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
...
</dependencies>

2.2.4 加入Maven插件

1
2
3
4
5
6
7
8
9
10
11
12
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes> <!--包括目录下的 .properties、.xml 文件都会被扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>

2.2.5 编写 Student 实体类

在 domain 包中创建该文件

1
2
3
4
public class Student{
private Integer id; //属性名尽量与列名相同
...
}

2.2.6 编写 Dao 接口 StudentDao

在 dao 包中创建该文件

1
2
3
4
5
public interface StudentDao {
List<Student> selectStudents(); //查询所有数据
Student selectStudentById(Integer id);
int insertStudent(Student student);
}

由于Mapper的动态代理方式,无需编写 Dao 的实现类

2.2.7 编写 Dao 接口 Mapper 映射文件来映射SQL语句

注意:

  1. 在 dao 包中创建文件 StudentDao.xml
  2. StudentDao.xml 文件名称要与接口 StudentDao 一样(区分大小写)

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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="top.JoyDee.dao.StudentDao">
<!--命名空间,应使用dao接口的全限定名称,实现与dao接口绑定,并隔离其他的不同语句-->

<select id="selectStudents" resultType="top.JoyDee.domain.Student">
select id,name,email,age from student order by id
</select>
<!--将已映射的 select 语句匹配到对应名称、参数和返回类型的方法-->
<!--接下来,你就可以用top.JoyDee.dao.StudentDao.selectStudents()来调用这个映射语句了-->
<!--id即为dao接口的方法名-->
<select id="selectStudentById" parameterType = "java.lang.Integer" resultType="top.JoyDee.domain.Student">
select id,name,email,age from student where id = #{studentId}
</select>

<insert id="insertStudent">
insert into student values(#{id},#{name},#{email},#{age})
</insert>

</mapper>

在IDEA中可以设置代码模板:

2.2.8 创建 MyBatis 主配置文件

在项目 src/main 下创建 resources 目录,然后在该目录下创建主配置文件 mabatis.xml(名称自定义)

创建resources 目录时别忘记右键设置其为 resources root

其内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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>
<!--settings标签能够控制MyBatis全局行为-->
<!--<settings>
设置MyBatis的输出日志
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>-->

<!--设置别名,为 Java 类型设置一个缩写名字,降低冗余的全限定类名书写-->
<typeAliases>
<package name="top.JoyDee.domain"/>
<!--name:实体类所在的包名-->
</typeAliases>

<!--sql mapper(sql映射文件)的位置-->
<mappers>
<!--name:该包中的所有mapper.xml一次都能加载-->
<!--使用package的要求:
1.mapper文件名和dao接口名必须完全一样,包括大小写
2.mapper文件和dao接口必须在同一目录下
-->
<package name="top.JoyDee.dao"/>
</mappers>
</configuration>

2.2.9 使用数据库属性配置文件

为方便对数据库连接的管理,DB连接的“四要素”数据一般都存放在一个专门的属性文件中,而 MyBatis 主配置文件需从这个属性文件中读取这些数据,配置环境并获取数据源。

在 classpath 路径下的 resources 目录创建 jdbc.properties 文件(名称自定义)

1
2
3
4
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
jdbc.user=root
jdbc.password=root

2.2.10 创建 MyBatisUtil 工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MyBatisUtils {
//定义SqlSessionFactory
private static SqlSessionFactory factory = null;
static { //使用静态代码块保证SqlSessionFactory是单例类
String config = "mybatis.xml"; //mybatis主配置文件
try{
//使用Resources工具类来读取主配置文件
InputStream in = Resources.getResourceAsStream(config);
//创建SqlSessionFactoryBuilder对象,目的是获取SqlSessionFactory
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}

public static SqlSession getSqlSession(){
//获取SqlSession,SqlSession能够执行SQL语句
SqlSession sqlSession = null;
if(factory != null){
sqlSession = factory.openSession();
}
return sqlSession;
}
}

2.2.10 创建测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class TestMyBatis {
@Test
public void testSelectStudent(){
//调用MyBatisUtils自定义工具类,获取SqlSession,从而执行SQL语句
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//调用SqlSession的getMapper()方法,来获取代理对象,从而获取指定接口的实现类对象
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectStudents();
for(Student stu : students){
System.out.println(stu);
}
sqlSession.close();
}

@Test
public void testInsertStudent(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);

Student student = new Student();
student.setId(309);
student.setAge(20);
student.setName("Ace");
student.setEmail("ace@qq.com");

int res = dao.insertStudent(student); //传入对象
sqlSession.commit();
System.out.println("添加对象的数量:" + res);
sqlSession.close();
}
}

Chapter 3. MyBatis 对象分析

3.1 四个实例

当 MyBatis 与一些依赖注入框架(如 Spring),SqlSession 将被依赖注入框架创建并注入,此时就无需使用 SqlSessionFactoryBuilder 或者 SqlSessionFactory

3.1.1 Resources 工具类

Resources 类,帮助开发者从类路径下、文件系统或一个 web URL 中加载资源文件。许多方法通过加载并解析资源文件,返回不同类型的IO流对象。

3.1.2 SqlSessionFactoryBuilder 类

SqlSessionFactoryBuilder 有五个 build() 方法,每一种的方法能够让开发者从不同的资源中创建一个 SqlSessionFactory 实例,当 SqlSessionFactory 实例即工厂对象被创建后,SqlSessionFactoryBuilder 就完成了其使命,能够被销毁了。

3.1.3 SqlSessionFactory 接口

SqlSessionFactory 接口对象是一个系统开销较大的对象,且是线程安全的,故一个应用只需一个该对象即可。

通过调用 SqlSessionFactory 接口的 openSession() 方法,就能够创建 SqlSession 对象了:

  • openSession(true):创建一个有自动提交功能的 SqlSession
  • openSession(false)openSession():创建一个非自动提交功能(即需要手动提交)的 SqlSession

3.1.4 SqlSession 接口

SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以 SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。

由于 SqlSession 接口对象是线程不安全的,故每次数据库会话结束前需马上调用其 close() 方法,将其关闭。若再次需要会话,则需要再次创建(在方法内部创建)

3.2 MyBatis框架 Dao 代理

MyBatis 框架抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对DB进行操作,这种对 Dao 的实现方式称为 Mapper 的动态代理方式。

Mapper 动态代理方式,无需开发者去实现 Dao 接口,而是由 MyBatis 结合映射文件 mapper 来自动生成的动态代理来实现的。故,只需要调用 SqlSessiongetMapper() 方法,就能够获取指定接口的实现类对象,注意该方法参数为指定 Dao 接口类的 class 值,如下:

1
2
SqlSession session = factory.openSession(); //获取session
StudentDao dao = session.getMapper(StudentDao.class);

Chapter 4. XML映射器

"MyBatis的真正强大在于它的语句映射……让用户能更专注于SQL代码”。

SQL 映射文件有以下这些顶级元素:

  • <cache>
  • <cache-ref>
  • <resultMap>:描述如何从数据库结果集中,加载对象,是最强大的元素!
  • <insert>/<update>/<delete>/<select> :映射插入/更新/删除/查询语句。

4.1 理解参数

4.2 结果映射