一、框架

1.1 框架概念

框架就是软件的半成品,框架完成了软件开发过程中的通用操作,程序猿只需要很少或者不用加工就能够实现特定的功能,从而简化开发人员在软件开发中的步骤,提高开发效率。

1.2 常用框架

  • MVC框架:简化了Servlet的开发步骤,负责和前端进行交互
    • Struts2
    • SpringMVC
  • 持久层框架:完成数据库操作的框架,负责和数据库交互
    • MyBatis
    • Hibernate
    • 胶水框架:Spring

SSM:Spring + SpringMVC + MyBatis
SSH:Spring + Struts2 + Hibernate

二、MyBatis简介

2.1 MyBatis介绍

MyBatis是一个半自动ORM框架
ORM(Object Relation Mapping)对象关系映射,将Java中的一个对象和数据表中的一行记录一一对应。
ORM框架提供了实体类与数据表的映射关系,通过映射文件的配置,实现了对象的持久化。

MyBatis特点:

  • 支持自定义SQL、存储过程
  • 对原有的JDBC进行了封装,几乎消除了所有JDBC的代码,让开发人员只需要关注SQL语句本身
  • 支持XML和注解配置的方式自动完成ORM操作,实现结果映射

2.2 MyBatis部署

框架部署就是把框架引入到我们自己的项目里

2.2.1 创建Maven项目

  • Java项目
  • Web项目

2.2.2 在项目中添加MyBatis依赖

  • 在 pom.xml 中添加依赖
    • mybatis
    • mysqldriver
1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>

2.2.3 创建MyBatis配置文件

  1. 在resources中创建名为mybatis-config.xml的文件
    在这里插入图片描述
  2. 在mybatis-config.xml文件中配置数据库连接信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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>

<!--在environments中配置数据库连接信息-->
<!--一个environments标签中可以定义而多个environment标签,
每个environment标签可以定义一套连接配置-->
<!--default用来指定使用哪一个environment-->
<environments default="mysql">
<!--transactionManager标签用于配置数据库的管理方式-->
<!--dataSource标签就是用来配置数据库连接信息-->
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db1?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

</configuration>

2.3 MyBatis框架使用

案例:学生信息的数据库操作

2.3.1 创建数据表

tb_students
SQL语句如下:

1
2
3
4
5
6
create table tb students(
sid int primary key auto increment,
stu_num char(5) not null unique,
stu_name varchar(20) not null,
stu_gender char(2) not null,
stu_age int not null);

2.3.2 创建实体类

在这里插入图片描述

2.3.3 创建DAO接口,定义操作方法

在这里插入图片描述

2.3.4 创建DAO接口下的映射文件

  • resources目录下,新建名为mappers文件夹
  • mappers中新建名为StudentMapper.xml的映射文件(根据模板创建)
  • 在映射文件中对DAO中定义的方法进行实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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文件相当于DAO接口的‘实现类’,namespace属性要指定`实现`DAO接口的全限定名-->
<mapper namespace="com.qfedu.dao.StudentDAO">
<insert id="insertStudent" parameterType="com.qfedu.pojo.Student">
insert into tb_student(stu_num,stu_name,stu_gender,stu_age)
values(#{stuNum},#{stuName},#{stuGender},#{stuAge})
</insert>

<delete id="deleteStudent">
delete from tb_students where stu_num = #{stuNum};
</delete>

</mapper>

2.3.5 将映射文件添加到主配置文件

在这里插入图片描述

2.4 单元测试

2.4.1 添加单元测试依赖

1
2
3
4
5
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>

2.4.2 创建单元测试类

被测试类名后,alt + insert – 选择Test
在这里插入图片描述
在这里插入图片描述

2.4.3 测试代码

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.qfedu.dao;

import com.qfedu.pojo.Student;
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 static org.junit.Assert.*;

/**
* @auther xiaochen
* @create 2022-03-22 9:13
*/
public class StudentDAOTest {

@org.junit.Test
public void insertStudent() {
try {
//加载配置文件(连接信息)
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

//会话工厂,连接需要连接信息
SqlSessionFactory factory = builder.build(is);

//会话(连接)
SqlSession sqlSession = factory.openSession();
//通过会话获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//测试StudentDAO中的方法
int i = studentDAO.insertStudent(new Student(0, "10001", "飞飞", "男", 21));
//需要手动提交
sqlSession.commit();

System.out.println(i);


} catch (IOException e) {
e.printStackTrace();
}

}

@org.junit.Test
public void deleteStudent() {
}
}

三、MyBatis的CRUD操作

案例:学生信息的增删查改

3.1 添加操作

3.2 删除操作

根据学号删除一条学生信息

  1. 在StudentDAO中定义删除方法
    在这里插入图片描述

  2. 在StudentMapper.xml中对接口方法进行实现
    在这里插入图片描述

  3. 单元测试:在StudentDAO的测试类中添加测试方法

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
@org.junit.Test
public void deleteStudent() {

//不能保证文件名一定是正确的,所以可能会抛出异常,需要进行捕获
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

//sqlSessionFactory表示MyBatis的会话工厂
SqlSessionFactory factory = builder.build(is);

//sqlSession表示MyBatis与数据库之间的会话:通过工厂方法设计模式
SqlSession sqlSession = factory.openSession();

//通过SqlSession对象调用getMapper方法来获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//调用被测试方法
int i = studentDAO.deleteStudent("10001");
//提交事务
sqlSession.commit();
System.out.println(i);
} catch (IOException e) {
e.printStackTrace();
}


}

3.3 修改操作

根据学生学号,修改学生信息

  1. 在StudentDAO定义修改方法
    在这里插入图片描述

  2. 在StudentMapper.xml中对接口方法进行实现
    在这里插入图片描述

  3. 单元测试

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
@Test
public void testUpdateStudent(){

//不能保证文件名一定是正确的,所以可能会抛出异常,需要进行捕获
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

//sqlSessionFactory表示MyBatis的会话工厂
SqlSessionFactory factory = builder.build(is);

//sqlSession表示MyBatis与数据库之间的会话:通过工厂方法设计模式
SqlSession sqlSession = factory.openSession();

//通过SqlSession对象调用getMapper方法来获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//调用被测试方法
int i = studentDAO.updateStudent(new Student(0, "10001", "佳佳", "男", 21));
//断言
assertEquals(1,i);
//提交事务
sqlSession.commit();
System.out.println(i);
} catch (IOException e) {
e.printStackTrace();
}
}

其中,assertEquals()方法表示断言,如果与期望值不同则会出现断言异常。
在这里插入图片描述

3.4 查询操作-查询所有数据操作

  1. 在StudentDAO中定义查询所有学生的方法
    在这里插入图片描述

  2. 在StudentMapper.xml对接口方法进行实现
    定义实体类和数据库表的映射关系在这里插入图片描述
    引用实体类和数据库表的映射关系
    在这里插入图片描述

  3. 单元测试

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
@Test
public void testListStudent(){

//不能保证文件名一定是正确的,所以可能会抛出异常,需要进行捕获
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

//sqlSessionFactory表示MyBatis的会话工厂
SqlSessionFactory factory = builder.build(is);

//sqlSession表示MyBatis与数据库之间的会话:通过工厂方法设计模式
SqlSession sqlSession = factory.openSession();

//通过SqlSession对象调用getMapper方法来获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//调用被测试方法
List<Student> students = studentDAO.listStudent();
for (Student student : students) {
System.out.println(student);
}
//断言
assertNotNull(students);
//查询操作不需要提交事务,因为不会更改数据库

} catch (IOException e) {
e.printStackTrace();
}
}

3.5 查询操作-查询单条记录

  1. 在StudentDAO中定义查询所有学生的方法
    在这里插入图片描述

  2. 在StudentMapper.xml对接口方法实现
    在这里插入图片描述

  3. 单元测试

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
@Test
public void testQueryStudent(){

//不能保证文件名一定是正确的,所以可能会抛出异常,需要进行捕获
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

//sqlSessionFactory表示MyBatis的会话工厂
SqlSessionFactory factory = builder.build(is);

//sqlSession表示MyBatis与数据库之间的会话:通过工厂方法设计模式
SqlSession sqlSession = factory.openSession();

//通过SqlSession对象调用getMapper方法来获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//调用被测试方法
Student student = studentDAO.queryStudent("10001");
System.out.println(student);
//断言
assertNotNull(student);

} catch (IOException e) {
e.printStackTrace();
}
}

3.6 查询操作-多参数查询

在MyBatis进行操作时:

  1. 如果操作方法只有一个简单类型或者字符串类型的参数,在Mapper配置中可以直接通过#{str}直接获取
  2. 如果操作方法只有一个对象类型的参数,在Mapper配置中可以直接通过#{attrName}来获取对象的指定属性值
  3. 如果操作方法有一个Map类型,在Mapper配置中可以直接通过#{key}获取key对应的value
  4. 如果操作方法有多个参数,可以使用@Param注解声明参数的别名

分页查询(参数 start,pageSize)

  1. 在StudentDAO定义分页查询的方法
    在这里插入图片描述

  2. 在StudentMapper.xml对接口方法进行实现,,使用#{别名}获取到指定的参数
    在这里插入图片描述

  3. 单元测试

    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
    @Test
    public void testListStudentByPage(){

    //不能保证文件名一定是正确的,所以可能会抛出异常,需要进行捕获
    try {
    InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
    //SqlSessionFactoryBuilder
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

    //sqlSessionFactory表示MyBatis的会话工厂
    SqlSessionFactory factory = builder.build(is);

    //sqlSession表示MyBatis与数据库之间的会话:通过工厂方法设计模式
    SqlSession sqlSession = factory.openSession();

    //通过SqlSession对象调用getMapper方法来获取DAO对象
    StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
    //调用被测试方法
    List<Student> students = studentDAO.listStudentByPage(0,2);

    for (Student student : students) {
    System.out.println(student);
    }
    //断言
    assertNotNull(students);

    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    注意:如果DAO操作方法没有通过@Param指定参数别名,在SQL中也可以使用arg0,arg1,...或者param1,param2,...的方式来获取参数。

3.7 查询操作-查询总记录数

  1. 在StudentDAO中定义操作方法
    在这里插入图片描述

  2. 在StudentMapper.xml中实现接口方法,通过resultType指定当前操作的返回类型为int
    在这里插入图片描述

  3. 单元测试

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
@Test
public void testgetCount(){

//不能保证文件名一定是正确的,所以可能会抛出异常,需要进行捕获
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

//sqlSessionFactory表示MyBatis的会话工厂
SqlSessionFactory factory = builder.build(is);

//sqlSession表示MyBatis与数据库之间的会话:通过工厂方法设计模式
SqlSession sqlSession = factory.openSession();

//通过SqlSession对象调用getMapper方法来获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//调用被测试方法

int count = studentDAO.getCount();
System.out.println(count);

} catch (IOException e) {
e.printStackTrace();
}
}

3.7 添加操作-主键回填

  • StudentMapper.xml中添加操作标签–insert
1
2
3
4
5
6
<!--useGeneratedKey 表示设置添加操作是否需要回填生成的主键-->
<!--keyProperty 设置回填的主键复制到参数对象中的哪一个属性-->
<insert id="insertStudent" useGeneratedKeys="true" keyProperty="stuId">
insert into tb_students(stu_num,stu_name,stu_gender,stu_age)
values(#{stuNum},#{stuName},#{stuGender},#{stuAge})
</insert>

四、工具类封装

  • 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* @auther xiaochen
* @create 2022-03-23 8:28
*/
//工具类的目标是对外提供SQLSession
public class MyBatisUtil {

private static SqlSessionFactory factory;
//当我们在创建一个ThreadLocal变量后,每个线程对其进行访问的时候访问的都是线程自己的变量,这样就不会存在线程不安全问题。
private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();


static {

try {
//加载MyBatis配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//工厂是单例的,所以只加载一次就够了
//不能每做一顿红烧肉就开一家饭店
factory = builder.build(is);
} catch (IOException e) {
e.printStackTrace();
}

}

public static SqlSessionFactory getFactory() {
return factory;
}


public static SqlSession getSqlSession() {
SqlSession sqlSession = local.get();
if (sqlSession == null) {
sqlSession = factory.openSession();
local.set(sqlSession);
}
return factory.openSession();
}


public static <T extends Object> T getMapper(Class<T> c) {
SqlSession sqlSession = getSqlSession();
return sqlSession.getMapper(c);
}

}

五、事务管理

  • SqlSession功能:
  1. getMapper(DAO.class):获取Mapper(DAO对象的实例)
  2. 事务管理

5.1 手动提交事务

测试类中的手动事务管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@org.junit.Test
public void insertStudent() {

SqlSession sqlSession = MyBatisUtil.getSqlSession();
//1.当获取SqlSession对象时,就默认开启了事务
try {
//通过会话获取DAO对象
StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
//测试StudentDAO中的方法
Student student = new Student(5, "10009", "周杰伦", "男", 28);
int i = studentDAO.insertStudent(student);
//2.操作成功之后,需要手动提交事务
sqlSession.commit();

System.out.println(student);
} catch (Exception e) {
//3.操作出现异常,需要对事务进行rollback回滚事务
sqlSession.rollback();
}
}

5.2 自动提交事务

通过SqlSessionFactory调用openSession方法获取SQLSession对象时,可以通过参数来设置事务是否自动提交:

  • 如果参数设置为true,表示自动事务提交
  • 如果不设置参数或者设置为false,表示手动事务提交

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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

/**
* @auther xiaochen
* @create 2022-03-23 8:28
*/
//工具类的目标是对外提供SQLSession
public class MyBatisUtil {

private static SqlSessionFactory factory;
//当我们在创建一个ThreadLocal变量后,每个线程对其进行访问的时候访问的都是线程自己的变量,这样就不会存在线程不安全问题。
private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();


static {

try {
//加载MyBatis配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//工厂是单例的,所以只加载一次就够了
//不能每做一顿红烧肉就开一家饭店
factory = builder.build(is);
} catch (IOException e) {
e.printStackTrace();
}

}

public static SqlSessionFactory getFactory() {
return factory;
}

//自动提交事务
public static SqlSession getSqlSession(boolean isAutoCommit) {
SqlSession sqlSession = local.get();
if (sqlSession == null) {
sqlSession = factory.openSession(isAutoCommit);
local.set(sqlSession);
}
return sqlSession;
}

//手动提交事务,以重载的方式实现
public static SqlSession getSqlSession() {
return getSqlSession(false);
}

//自动提交事务
//直接获取DAO就是不想进行手动事务管理,所以直接设置为自动事务提交
public static <T extends Object> T getMapper(Class<T> c) {
SqlSession sqlSession = getSqlSession(true);
return sqlSession.getMapper(c);
}

}

测试操作

  1. 手动事务提交
    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
    @org.junit.Test
    public void insertStudent() {

    SqlSession sqlSession = MyBatisUtil.getSqlSession(false);
    //1.当获取SqlSession对象时,就默认开启了事务
    try {
    //通过会话获取DAO对象
    StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
    //测试StudentDAO中的方法
    Student student = new Student(5, "10009", "周杰伦", "男", 28);
    int i = studentDAO.insertStudent(student);

    //操作1
    //操作2
    //...
    //操作3

    //如果需要使用SqlSession进行多步操作,建议使用手动提交事务

    //2.操作成功之后,需要手动提交事务
    sqlSession.commit();

    System.out.println(student);
    } catch (Exception e) {
    //3.操作出现异常,需要对事务进行rollback回滚事务
    sqlSession.rollback();
    }
    }
  2. 自动事务提交
1
2
3
4
5
6
@org.junit.Test
public void deleteStudent() {
StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class);
int i = studentDAO.deleteStudent("10001");
//提交事务
}

五、MyBatis主配置文件

mybatis-config.xml是MyBatis框架的主配置文件,主要用于配置MyBatis数据源以及属性信息

5.1 properties标签

用于设置键值对,或者加载属性文件

  • 在resources目录下创建jdbc.properties文件,配置键值对如下
1
2
3
4
mysql_driver=com.mysql.jdbc.Driver
mysql_url=jdbc:mysql://localhost:3306/db1?useSSL=true
mysql_username=root
mysql_password=123456
  • 在mybatis-config.xml中通过properties标签引用jdbc.properties文件;
  • 引入文件之后,在配置environment时可以直接使用jdbc.properties的key来获取对应的value
    在这里插入图片描述
    注意:${}是properties文件中的变量占位符,#{}是sql的参数占位符。

5.2 setting标签

1
2
3
4
5
6
7
<!--设置mybatis的属性-->
<settings>
<!-- 启动二级缓存-->
<setting name="cacheEnabled" value="true"/>
<!-- 启动延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>

8.3 typeAliases标签

1
2
3
4
5
<!--typeAliases标签用于给实体类取别名,在映射文件中可以直接使用别名来替代实体类的全限定名-->
<typeAliases>
<typeAlias type="com.qfedu.pojo.Student" alias="Student"></typeAlias>
<typeAlias type="com.qfedu.pojo.Book" alias="Book"></typeAlias>
</typeAliases>

5.4 plugins标签

1
2
3
4
<!--plugins标签,用于配置MyBatis插件(分页插件)-->
<plugins>
<plugin interceptor=""></plugin>
</plugins>

5.5 environments标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 在environments配置数据库连接信息 -->
<!-- 在environments标签中可以定义多个environment标签,每个environment标签可以定义一套连接配置 -->
<!-- default属性,用来指定使用哪个environment标签 -->
<environments default="mysql">

<!-- environment 标签用于配置数据库连接信息 -->
<environment id="mysql">

<!--transactionManager标签用于配置数据库管理方式
type="JDBC" 可以进行事务的提交和回滚操作
type="MANAGED" 依赖容器完成事务管理,本身不进行事务的提交和回滚操作 -->
<transactionManager type="JDBC"></transactionManager>

<!--dataSource标签就是用来配置数据库连接信息 POOLED|UNPOOLED -->
<dataSource type="POOLED">
<property name="driver" value="${mysql_driver}"/>
<property name="url" value="${mysql_url}"/>
<property name="username" value="${mysql_username}"/>
<property name="password" value="${mysql_password}"/>
</dataSource>
</environment>

</environments>

5.6 mappers标签

加载映射配置(映射文件、DAO注解)

1
2
3
4
<!--mappers标签用于载入映射文件-->
<mappers>
<mapper resource="mappers/StudentMapper.xml"></mapper>
</mappers>

六、映射文件

6.1 MyBatis Mapper初始化

XML文件解析:读取xml文件中的标签配置封装到Java对象中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n7eXPOJ3-1648176376717)(imgs/1616487875112.png)]

6.2 mapper根标签

mapper文件相当于DAO接口的‘实现类’,namespace属性要指定实现DAO接口的全限定名

6.3 insert标签

声明添加操作(sql: insert …)

常用属性

id属性,绑定对应DAO接口中的方法

parameterType属性,用以指定接口中对应方法的参数类型(可省略)

useGeneratedKeys属性, 设置添加操作是否需要回填生成的主键

keyProperty属性,指定回填的id设置到参数对象中的哪个属性

timeout属性,设置此操作的超时时间,如果不设置则一直等待

主键回填

1
2
3
4
<insert id="insertStudent" useGeneratedKeys="true" keyProperty="stuId">
insert into tb_students(stu_num, stu_name, stu_gender, stu_age)
values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
</insert>
1
2
3
4
5
6
7
<insert id="insertStudent" >
<selectKey keyProperty="stuId" resultType="java.lang.Integer">
select last_insert_id()
</selectKey>
insert into tb_students(stu_num, stu_name, stu_gender, stu_age)
values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
</insert>

6.4 delete标签

声明删除操作

6.5 update标签

声明修改操作

6.6 select标签

声明查询操作

  • id属性, 指定绑定方法的方法名

  • parameterType属性,设置参数类型

  • resultType属性,指定当前sql返回数据封装的对象类型(实体类)

  • resultMap属性,指定从数据表到实体类的字段和属性的对应关系

  • useCache属性,指定此查询操作是否需要缓存

  • timeout属性,设置超时时间

6.7 resultMap标签

1
2
3
4
5
6
7
8
<!-- resultMap标签用于定义实体类与数据表的映射关系(ORM) -->
<resultMap id="studentMap" type="Student">
<id column="sid" property="stuId"/>
<result column="stu_num" property="stuNum"/>
<result column="stu_name" property="stuName"/>
<result column="stu_gender" property="stuGender"/>
<result column="stu_age" property="stuAge"/>
</resultMap>

6.8 cache标签

设置当前DAO进行数据库操作时的缓存属性设置

1
<cache type="" size="" readOnly="false"/>

6.9 sql和include

SQL片段

1
2
3
4
5
<sql id="wanglaoji">sid , stu_num , stu_name , stu_gender , stu_age</sql>

<select id="listStudents" resultMap="studentMap">
select <include refid="wanglaoji"/> from tb_students
</select>

七、分页插件

分页插件是一个独立于MyBatis框架之外的第三方插件;

7.1 添加分页插件的依赖

PageHelper

1
2
3
4
5
6
 <!-- pagehelper分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>

7.2 配置插件

在mybatis的主配置文件mybatis-config.xml中通过plugins标签进行配置

1
2
3
4
<!--plugins标签,用于配置MyBatis插件(分页插件)-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

7.3 分页实例

对学生信息进行分页查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void testListStudentsByPage() {
StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class); //sqlSession
PageHelper.startPage(1, 4);
List<Student> students = studentDAO.listStudents();

PageInfo<Student> pageInfo = new PageInfo<Student>(students);
//pageInfo中就包含了数据及分页信息
List<Student> list = pageInfo.getList();
for (Student student : list) {
System.out.println(student);
}

}

带条件分页

1
2
3
4
5
6
7
8
9
@Test
public void testListStudentsByPage() {
StudentDAO studentDAO = MyBatisUtil.getMapper(StudentDAO.class);
PageHelper.startPage(2,4);
//List<Student> students = studentDAO.listStudents();
List<Student> list = studentDAO.listStudentsByGender("男");
PageInfo<Student> pageInfo = new PageInfo<Student>(list);
//pageInfo中就包含了数据及分页信息
}

八、关联映射

8.1 实体关系

实体——数据实体,实体关系指的就是数据与数据之间的关系

例如:用户和角色、房屋和楼栋、订单和商品

实体关系分为以下四种:

一对一关联

实例:人和身份证、学生和学生证、用户基本信息和详情

数据表关系:

  • 主键关联(用户表主键 和详情主键相同时,表示是匹配的数据)

    1616550990633

  • 唯一外键关联

    1616551159843

一对多关联多对一关联

实例:

  • 一对多: 班级和学生 、 类别和商品、楼栋和房屋
  • 多对一:学生和班级 、 商品和类别

数据表关系:

  • 在多的一端添加外键和一的一段进行关联

多对多关联

实例:用户和角色、角色和权限、房屋和业主、学生和社团、订单和商品

数据表关系:建立第三张关系表添加两个外键分别与两张表主键进行关联

用户(user_id) 用户角色表(uid,rid) 角色(role_id)

8.2 创建项目,部署MyBatis框架

  • 创建web项目(maven)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--添加web依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
  • 部署MyBatis框架

    • 添加依赖
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!--添加MyBatis依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
    </dependency>
  • 工具类

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    package com.qfedu.utils;

    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;

    /**
    * @auther xiaochen
    * @create 2022-03-29 20:38
    */
    public class MyBatisUtil {
    private static SqlSessionFactory factory;
    private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();


    static {
    try {
    InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
    factory = new SqlSessionFactoryBuilder().build(is);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
    return factory;
    }

    public static SqlSession getSqlSession(boolean isAutoCommit) {
    SqlSession sqlSession = local.get();
    if (sqlSession == null) {
    sqlSession = factory.openSession(isAutoCommit);
    local.set(sqlSession);
    }
    return sqlSession;
    }


    public static SqlSession getSqlSession() {
    return getSqlSession(false);
    }


    public static <T extends Object> T getMapper(Class<T> c) {

    SqlSession sqlSession = getSqlSession(true);
    return sqlSession.getMapper(c);
    }
    }