SSM系列第5篇数据库框架

基本概念

Mybatis是由Apache的一个开源项目iBatis,2010年迁移到了谷歌,iBatis3.x正式更名为Mybatis。是一个基于Java持久层框架包括SQL Maps和Data Access Object(DAO),Mybatis支持定制化SQL、存储过程以及高级映射的特性,几乎避免了所有的JDBC代码和手动参数以及获取结果集,通过简单的xml或注解用于配置和原始映射,是一个非常优秀的半自动ORM框架。相较于jpa,能处理较复杂的SQL语句,性能也高于jpa

基础案例

1.首先先加入相关的依赖,需要注意mysql版本带来的问题
2.创建mybatis配置文件,对mybatis进行配置,配置文件中通过environment的id属性来区分不同的环境
3.创建业务接口,业务xml,xml中的id要和接口的相同
4.在测试中,获取配置文件,获取SqlSessionFactoryBuilder,获取SqlSessionFactory(这里需要开启事务)
5.最后获取SqlSession,通过SqlSession来获取接口,调用相应的dao方法

相关代码

相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!--mybatis核心-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>

<!--junit测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>

创建用户表

1
2
3
4
5
6
7
8
9
10
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`password` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`age` int(0) NULL DEFAULT NULL,
`sex` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`email` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4;

mybatis-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<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?serverTimezone=GMT&amp;useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;useSSL=false&amp;allowPublicKeyRetrieval=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>

UserMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?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.eldpepar.mapper.UserMapper">

<insert id="insertUser">
INSERT INTO t_user
values (null, 'admin', '123456', 23, '男', 'admin@eldpepar.com')
</insert>

</mapper>

UserMapper.java

1
2
3
4
5
package com.eldpepar.mapper;

public interface UserMapper {
int insertUser();
}

测试插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void testInsert() throws IOException {
//加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//获取SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//获取SqlSession,默认参数设置为true表示开启自动事务提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);

//获取mapper接口对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

//测试功能
int result = mapper.insertUser();
System.out.println(result);
}

查询案例

查询案例中,需要设置resultType(默认映射)和resultMap(自定义映射),如果字段名和属性名不一致的时候使用自定义映射。

代码示例

UserMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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.eldpepar.mapper.UserMapper">

<select id="selectUserById" resultType="com.eldpepar.pojo.User">
SELECT * FROM t_user WHERE id=#{id}
</select>

<select id="selectAll" resultType="com.eldpepar.pojo.User">
SELECT * FROM t_user
</select>
</mapper>

UserMapper.java

1
2
3
4
5
6
7
8
9
10
11
package com.eldpepar.mapper;

import com.eldpepar.pojo.User;

import java.util.List;

public interface UserMapper {
User selectUserById(int id);

List<User> selectAll(@Param("id") int);
}

User.java

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.eldpepar.pojo;

public class User {
private Integer id;
private String username;
private String password;
private Integer age;
private String sex;
private String email;

public User(Integer id, String username, String password, Integer age, String sex, String email) {
this.id = id;
this.username = username;
this.password = password;
this.age = age;
this.sex = sex;
this.email = email;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", email='" + email + '\'' +
'}';
}
}

测试查询数据

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
@Test
public void selectId() throws IOException {
//加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//获取SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//获取SqlSession,默认参数设置为true表示开启自动事务提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);

//获取mapper接口对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

//测试功能
User user = mapper.selectUserById(1);
System.out.println(user);
}

@Test
public void selectAll() throws IOException {
//加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//获取SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//获取SqlSession,默认参数设置为true表示开启自动事务提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);

//获取mapper接口对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

//测试功能
List<User> users = mapper.selectAll();
users.forEach(System.out::println);
}

核心配置

1.引入properties配置文件,使用的时候,用${}来引用

1
2
3
4
5
6
7
8
9
10
11
12
<!--引入properties文件,此时就可以${属性名}的方式访问属性值-->
<properties resource="jdbc.properties"></properties>
<dataSource type="POOLED">
<!--设置驱动类的全类名-->
<property name="driver" value="${jdbc.driver}"/>
<!--设置连接数据库的连接地址-->
<property name="url" value="${jdbc.url}"/>
<!--设置连接数据库的用户名-->
<property name="username" value="${jdbc.username}"/>
<!--设置连接数据库的密码-->
<property name="password" value="${jdbc.password}"/>
</dataSource>

2.表中下划线转驼峰,延时加载

1
2
3
4
5
6
<settings>
<!--将表中字段的下划线自动转换为驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>

3.typeAlias设置某个具体的类型的别名,通过type设置别名的类型的全类名,通过alias设置此类型的别名,且别名不区分大小写。若不设置此属性,该类型拥有默认的别名,即类名。如果需要一个包下所有类,则使用package

1
2
3
4
5
6
<typeAliases>
<typeAlias type="com.eldpepar.bean.User"></typeAlias>
<typeAlias type="com.eldpepar.bean.User" alias="user">
<!--以包为单位,设置改包下所有的类型都拥有默认的别名,即类名且不区分大小写-->
<package name="com.eldpepar.bean"/>
</typeAliases>

4.transactionManager设置事物管理的方式,有JDBC和MANAGED两种。JDBC事物需要手动处理

5.dataSource设置数据源,POOLED使用数据库连接池,UNPOOLED不使用连接池,JNDI调用上下文数据源

配置模板

在实际开发过程中,数据库的配置,orm的映射等等过程,往往只需要修改一些简单的文件就可以实现相应的功能。为了简化操作,可以添加模板在idea中,方便下次直接使用

mybatis配置

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
<?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="jdbc.properties"></properties>

<typeAliases>
<package name=""></package>
</typeAliases>

<!--设置连接数据库的环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url"
value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入映射文件-->
<mappers>
<package name=""/>
</mappers>
</configuration>

mapper配置

1
2
3
4
5
6
7
<?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="">

</mapper>

添加步骤

1.进入设置页面,进入Edit选择File and Code Temp
2.输入文件名称和后缀进行添加

获取参数

1.MyBatis获取参数值的两种方式:${}和#{}

2.${}的本质就是字符串拼接,#{}的本质就是占位符赋值

3.${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号

SqlSession工具类

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
package com.eldpepar.util;
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;

public class SqlSessionUtils {
public static SqlSession getSqlSession(){
SqlSession sqlSession = null;

InputStream is = null;
try {
is = Resources.getResourceAsStream("mybatis-config.xml");
//获取SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//获取SqlSession,默认参数设置为true表示开启自动事务提交
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
e.printStackTrace();
}
return sqlSession;
}
}

多个字面量类型

若mapper接口中的方法参数为多个时,此时MyBatis会自动将这些参数放在一个map集合中

  • 以arg0,arg1…为键,以参数为值
  • 以param1,param2…为键,以参数为值

基本使用方法
1.只需要通过${}#{}访问map集合的键就可以获取相对应的值,其中${}需要手动加单引号

2.使用arg或者param都行,要注意的是,arg是从arg0开始的,param是从param1开始的

检测登录案例

1
2
3
4
<!--User checkLogin(String username,String password);-->
<select id="checkLogin" resultType="User">
select * from t_user where username = #{arg0} and password = #{arg1}
</select>

集合类型

若mapper接口中的方法需要的参数为多个时,此时可以手动创建map集合,将这些数据放在map中只需要通过${}和#{}访问map集合的键就可以获取相对应的值

登录示例

1
2
3
4
5
6
7
8
<!--User checkLoginByMap(Map<String,Object> map);-->
<!--方式二
@MapKey("id")
Map<String, Object> getAllUserToMap();
-->
<select id="checkLoginByMap" resultType="User">
select * from t_user where username = #{username} and password = #{password}
</select>

测试代码

1
2
3
4
5
6
7
8
9
10
@Test
public void checkLoginMap() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<>();
map.put("username","admin");
map.put("password","123456");
User user = mapper.checkLoginByMap(map);
System.out.println(user);
}

实体类类型

若mapper接口中的方法参数为实体类对象时 此时可以使用${}和#{},通过访问实体类对象中的属性名获取属性值

添加示例

1
2
3
4
<!--int insertUser(User user);-->
<insert id="insertUser">
insert into t_user values(null, #{username}, #{password}, #{age}, #{sex}, #{email})
</insert>

测试代码

1
2
3
4
5
6
7
8
9
@Test
public void insertUser() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(null,"Zhangsan","123456",23,"男","eldp@eldpepar.com");
int res = mapper.insertUser(user);

System.out.println(res);
}

@Param标识参数

通过@Param注解标识mapper接口中的方法参数,此时,会将这些参数放在map集合中
1.以@Param注解的value属性值为键,以参数为值
2.以param1,param2…为键,以参数为值
3.只需要通过${}和#{}访问map集合的键就可以获取相对应的值

登录验证

1
2
3
4
5
6
7
8
9
<!--User CheckLoginByParam(@Param("username") String username, @Param("password") String password);-->
<select id="CheckLoginByParam" resultType="User">
select * from t_user where username = #{username} and password = #{password}
</select>

<!--User CheckLogin(@Param("param1") String username, @Param("param2") String password);-->
<select id="CheckLogin" resultType="User">
select * from t_user where username = #{param1} and password = #{param2}
</select>

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void CheckLoginByParam() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.CheckLoginByParam("Zhangsan", "123456");

System.out.println(user);
}

@Test
public void CheckLogin() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.CheckLogin("Zhangsan", "123456");

System.out.println(user);
}

特殊SQL

在实际开发中,往往会有模糊查询、批量删除等等特殊需求的SQL

模糊查询

模糊查询有三种方式,第三种方式也是用到的最多的方式
模糊查询

1
2
3
4
5
6
<!--List<User> getUserByLike(@Param("username") String username);-->
<select id="getUserByLike" resultType="User">
<!--select * from t_user where username like concat('%',#{username},'%')-->
<!--select * from t_user where username like '%${username}%'-->
select * from t_user where username like "%"#{username}"%"
</select>

测试代码

1
2
3
4
5
6
7
@Test
public void getUserByLike() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.getUserByLike("Zhang");
users.forEach(System.out::println);
}

批量删除

批量删除中只能使用${},如果使用#{}会把数据看成整体,就无法实现批量的操作

批量删除

1
2
3
4
<!--int deleteMore(@Param("ids") String ids);-->
<delete id="deleteMore">
delete from t_user where id in (${ids})
</delete>

测试代码

1
2
3
4
5
6
7
@Test
public void deleteMore() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int result = mapper.deleteMore("4,5,6,7,8,9");
System.out.println(result);
}

动态设置表名

动态设置表名不能使用#来操作,因为表明是不可加单引号的

动态设置表明

1
2
3
4
<!--List<User> getUSernByTableName(@Param("tableName") String tableName); -->
<select id="getUserByTableName" resultType="User">
select * from ${tableName}
</selecet>

添加功能获取自增主键

使用场景
1.添加班级信息
2.获取新添加的班级id
3.为班级分配学生,即将某学生的班级id修改为新添加的班级id

配置方法
需要在mapper.xml中设置两个属性

  • userGeneratedKeyS: 设置使用自增的主键
  • keyProperty: 一五年增删改有统一的返回值是受影响的行数,因此只能将获取的自增主键放在传输的参数user对象的某个属性中

添加功能获取自增主键

1
2
3
4
<!--void insertUser(User user); -->
<insert id="insertUser" userGeneratedKey="true" keyProperty="id">
insert into t_user values (null, #{username}, #{password}, #{age}, #{sex}, #{email})
</insert>

测试代码

1
2
3
4
5
6
7
8
@Test
public void deleteMore() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(null, "ton", "123", 23, "男", "123@eldpepar.com");
mapper.insertUser(user);
System.out.println(user);
}

字段与属性冲突

有些情况下,表中的字段名和类中的属性名无法对应,为了解决这种情况,可以设置字段别名来解决

(一)字段别名方法

可以和在sql语句中,设置字段的别名解决字段冲突的问题

1
2
3
4
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultType="Emp">
select eid,emp_name empName,age,sex,email from t_emp
</select>

(二)修改全局配置

可以通过修改mybatis全局配置的方法,可以将下划线自动映射为驼峰

1
2
3
4
<settings>
<!-- 驼峰自动转下划线-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

(三)自定义映射resultMap

1.resultMap中的id属性表示映射的名称是唯一的,type表示需要映射的实体类的类型
2.子标签中的id表示映射的是主键,result表示的是映射的是普通字段
3.子标签中的property设置的是实体类中的属性名,column设置映射关系中表中的字段名

强制规则
如果字段名和实体类中的属性名相同,也需要进行映射,也就是需要列出全部属性

1
2
3
4
5
6
7
8
9
10
11
<resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column"emp_name"></result>
<result property="age" column"age"></result>
<result property="sex" column"sex"></result>
<result property="email" column"email"></result>
</resultMap>

<select id="getAllEmp" resultMap="empResultMap">
select * from t_emp
</select>

(四)多对一映射

处理多对一映射的映射通常有多种方式,也是实际开发中非常常见的一种需求,比如查询员工信息以及员工信息所对应的部门信息

一:级联属性赋值方式

这种方式并不常用
员工类

1
2
3
4
5
6
7
8
public class Emp {
private Integer eid;
private String empName;
private Integer age;
private String sex;
private String email;
private Dept dept;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<resultMap id="empAndDeptResultMapOne" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<result property="dept.did" column="did"></result>
<result property="dept.deptName" column="dept_name"></result>
</resultMap>

<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select>
二:association方法解决

其中的property属性表示的是需要处理多对的映射关系的属性名,javaType表示该属性的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<resultMap id="empAndDeptResultMapTwo" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept" javaType="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</association>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select>
三:分步查询方式

分步查询是执行多步来实现相关的查询业务,分步查询的优点是可以使用懒加载的方式,会更加的灵活。association中的select用于设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名),column用于设置分步查询的条件

1.查询员工信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
<association property="dept"
select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="did"></association>
</resultMap>
<!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
select * from t_emp where eid = #{eid}
</select>

2.查询部门信息

1
2
3
4
5
6
7
8
9
<!--此处的resultMap仅是处理字段和属性的映射关系-->
<resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
</resultMap>
<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap">
select * from t_dept where did = #{did}
</select>
延迟加载

延迟加载需要在核心配置文件中设置全局配置信息。
1.lazyLoadingEnable是延迟加载的全局开关,当开启时,所有关联的对象都会进行延迟加载。
2.aggressiveLazyLoading当开启时,任何方法调用都会加载对象所有属性,否则每个属性都会按需加载。
3.如果分步查询中的某一步不需要延迟加载,可以设置association和collection中的fetchType属性来控制,其中lazy是延迟加载,eager是立即加载。

(五)一对多映射

对一是对应的对象,对多是对应的集合。在一对多的业务中,经常需要获取部门以及部门中所有员工信息的这类需求,这里就需要用到一对多的映射关系来进行相应的处理。

一:使用collection

collection用来处理一对多的映射关系,其中ofType表示该属性对饮的集合中存储的数据的类型。

部门类

1
2
3
4
5
public class Dept {
private Integer did;
private String deptName;
private List<Emp> emps;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<resultMap id="DeptAndEmpResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="empName" column="emp_name"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
<result property="email" column="email"></result>
</collection>
</resultMap>

<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>
二:分步查询

分步查询同样可以使用前面的延迟加载,配置方式相同
1.查询部门信息

1
2
3
4
5
6
7
8
9
10
11
12
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
<id property="did" column="did"></id>
<result property="deptName" column="dept_name"></result>
<collection property="emps"
select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="did"></collection>
</resultMap>

<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">
select * from t_dept where did = #{did}
</select>

2.根据部门id查询部门中的所有员工

1
2
3
4
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select * from t_emp where did = #{did}
</select>

动态SQL

MyBatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题

if标签

1.if标签可通过test属性(即传递过来的数据)的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行
2.在where后面添加一个恒成立条件1=1

  • 这个恒成立条件并不会影响查询的结果
  • 这个1=1可以用来拼接and语句,例如:当empName为null时
    ①如果不加上恒成立条件,则SQL语句为select * from t_emp where and age = ? and sex = ? and email = ?,此时where会与and连用,SQL语句会报错
    ②如果加上一个恒成立条件,则SQL语句为select * from t_emp where 1= 1 and age = ? and sex = ? and email = ?,此时不报错

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp where 1=1
<if test="empName != null and empName !=''">
and emp_name = #{empName}
</if>
<if test="age != null and age !=''">
and age = #{age}
</if>
<if test="sex != null and sex !=''">
and sex = #{sex}
</if>
<if test="email != null and email !=''">
and email = #{email}
</if>
</select>

where标签

where和if一般结合使用

  • 若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
  • 若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and/or去掉
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp
<where>
<if test="empName != null and empName !=''">
emp_name = #{empName}
</if>
<if test="age != null and age !=''">
and age = #{age}
</if>
<if test="sex != null and sex !=''">
and sex = #{sex}
</if>
<if test="email != null and email !=''">
and email = #{email}
</if>
</where>
</select>

where标签不能去掉条件后多余的and/or

1
2
3
4
5
6
<if test="empName != null and empName !=''">
emp_name = #{empName} and
</if>
<if test="age != null and age !=''">
age = #{age}
</if>

trim标签

1.trim用于去掉或添加标签中的内容
2.常用属性

  • prefix:在trim标签中的内容的前面添加某些内容
  • suffix:在trim标签中的内容的后面添加某些内容
  • prefixOverrides:在trim标签中的内容的前面去掉某些内容
  • suffixOverrides:在trim标签中的内容的后面去掉某些内容

3.若trim中的标签都不满足条件,则trim标签没有任何效果,也就是只剩下select * from t_emp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp
<trim prefix="where" suffixOverrides="and|or">
<if test="empName != null and empName !=''">
emp_name = #{empName} and
</if>
<if test="age != null and age !=''">
age = #{age} and
</if>
<if test="sex != null and sex !=''">
sex = #{sex} or
</if>
<if test="email != null and email !=''">
email = #{email}
</if>
</trim>
</select>
1
2
3
4
5
6
7
8
//测试类
@Test
public void getEmpByCondition() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
List<Emp> emps= mapper.getEmpByCondition(new Emp(null, "张三", null, null, null, null));
System.out.println(emps);
}

choose、when、otherwise标签

1.choose、when、otherwise相当于if…else if..else
2.when至少要有一个,otherwise至多只有一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<select id="getEmpByChoose" resultType="Emp">
select * from t_emp
<where>
<choose>
<when test="empName != null and empName != ''">
emp_name = #{empName}
</when>
<when test="age != null and age != ''">
age = #{age}
</when>
<when test="sex != null and sex != ''">
sex = #{sex}
</when>
<when test="email != null and email != ''">
email = #{email}
</when>
<otherwise>
did = 1
</otherwise>
</choose>
</where>
</select>
1
2
3
4
5
6
7
@Test
public void getEmpByChoose() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
List<Emp> emps = mapper.getEmpByChoose(new Emp(null, "张三", 23, "男", "123@qq.com", null));
System.out.println(emps);
}

foreach标签

1.相关属性:

  • collection:设置要循环的数组或集合
  • item:表示集合或数组中的每一个数据
  • separator:设置循环体之间的分隔符,分隔符前后默认有一个空格,如,
  • open:设置foreach标签中的内容的开始符
  • close:设置foreach标签中的内容的结束符

2.批量删除:

1
2
3
4
5
6
7
<!--int deleteMoreByArray(Integer[] eids);-->
<delete id="deleteMoreByArray">
delete from t_emp where eid in
<foreach collection="eids" item="eid" separator="," open="(" close=")">
#{eid}
</foreach>
</delete>
1
2
3
4
5
6
7
@Test
public void deleteMoreByArray() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
int result = mapper.deleteMoreByArray(new Integer[]{6, 7, 8, 9});
System.out.println(result);
}

3.批量添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!--int insertMoreByList(@Param("emps") List<Emp> emps);-->
<insert id="insertMoreByList">
insert into t_emp values
<foreach collection="emps" item="emp" separator=",">
(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)
</foreach>
</insert>
```z

```java
@Test
public void insertMoreByList() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
Emp emp1 = new Emp(null,"a",1,"男","123@321.com",null);
Emp emp2 = new Emp(null,"b",1,"男","123@321.com",null);
Emp emp3 = new Emp(null,"c",1,"男","123@321.com",null);
List<Emp> emps = Arrays.asList(emp1, emp2, emp3);
int result = mapper.insertMoreByList(emps);
System.out.println(result);
}

SQL片段

  • sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入
  • 声明sql片段:标签
    1
    <sql id="empColumns">eid,emp_name,age,sex,email</sql>
  • 引用sql片段:标签
    1
    2
    3
    4
    <!--List<Emp> getEmpByCondition(Emp emp);-->
    <select id="getEmpByCondition" resultType="Emp">
    select <include refid="empColumns"></include> from t_emp
    </select>

缓存

缓存是将查询到的数据进行记录,下次访问的时候会从缓存中读取,不会进行新的查询。其中一级缓存是默认开启的。

缓存查询顺序
1.先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
2.如果二级缓存没有命中,再查询一级缓存
3.如果一级缓存也没有命中,则查询数据库
4.SqlSession关闭之后,一级缓存中的数据会写入二级缓存

一级缓存

1.一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
2.使一级缓存失效的四种情况:

  • 不同的SqlSession对应不同的一级缓存
  • 同一个SqlSession但是查询条件不同
  • 同一个SqlSession两次查询期间执行了任何一次增删改操作
  • 同一个SqlSession两次查询期间手动清空了缓存

二级缓存

1.二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
2.二级缓存开启的条件

  • 在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置
  • 在映射文件中设置标签
    1
    <cache/>

3.二级缓存必须在SqlSession关闭或提交之后有效
4.查询的数据所转换的实体类类型必须实现序列化的接口

  • 使二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

1.测试类
需要特别注意的是,之前实现的SqlSessionUtils中每次调用会new一个新的SqlSessionFactory,所有需要重新实现实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void testCache() {
try {
InputStream is = Resources.getReResourcesAsStream("mybaits-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().buid(is);
SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
System.out.println(mapper1.getEmpByEid(1));
sqlSession1.close();

SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
System.out.println(mapper2.getEmpByEid(1));
sqlSession2.close();
} catch(IOException e) {
e.printStackTrace();
}
}

2.相关配置

  • 在mapper配置文件中添加的cache标签可以设置一些属性
  • eviction属性:缓存回收策略

1.LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
2.FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
3.SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
4.WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
5.默认的是 LRU

  • flushInterval属性:刷新间隔,单位毫秒

1.默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句(增删改)时刷新

  • size属性:引用数目,正整数

1.代表缓存最多可以存储多少个对象,太大容易导致内存溢出

  • readOnly属性:只读,true/false

1.true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
2.false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false

第三方缓存EHCache

1.导入相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Mybatis EHCache整合包 -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
<!-- slf4j日志门面的一个具体实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>

2.创建配置文件(名字必须叫ehcache.xml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="D:\atguigu\ehcache"/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>

3.设置二级缓存的类型
在mapper配置文件中设置缓存的类型

1
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

4.加入logback日志
存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。创建logback的配置文件logback.xml,名字固定,不可改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 指定日志输出的位置 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志输出的格式 -->
<!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
</encoder>
</appender>
<!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
<!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
<root level="DEBUG">
<!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
<appender-ref ref="STDOUT" />
</root>
<!-- 根据特殊需求指定局部日志级别 -->
<logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
</configuration>

逆向工程

1.正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的
2.逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:

  • Java实体类
  • Mapper接口
  • Mapper映射文件

实现步骤

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
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
57
58
59
60
<dependencies>
<!-- MyBatis核心依赖包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<!-- 控制Maven在构建过程中相关配置 -->
<build>
<!-- 构建过程中用到的插件 -->
<plugins>
<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!-- 插件的依赖 -->
<dependencies>
<!-- 逆向工程的核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

2.创建核心配置文件

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>
<properties resource="jdbc.properties"/>
<typeAliases>
<package name=""/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name=""/>
</mappers>
</configuration>

3.创建逆向工程的配置文件(文件名必须是generatorConfig.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD(清新简洁版)
MyBatis3: 生成带条件的CRUD(奢华尊享版)
-->
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<!-- 数据库的连接信息 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis"
userId="root"
password="123456">
</jdbcConnection>
<!-- javaBean的生成策略-->
<javaModelGenerator targetPackage="com.atguigu.mybatis.pojo" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- SQL映射文件的生成策略 -->
<sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- Mapper接口的生成策略 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 逆向分析的表 -->
<!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
<!-- domainObjectName属性指定生成出来的实体类的类名 -->
<table tableName="t_emp" domainObjectName="Emp"/>
<table tableName="t_dept" domainObjectName="Dept"/>
</context>
</generatorConfiguration>

4.执行maven中的MBG插件中的generate目标

QBC

Query By Criteria根据条件来查询,其中必须要使用MyBatis3配置才支持生成example

1.selectByExample:按条件查询,需要传入一个example对象或者null;如果传入一个null,则表示没有条件,也就是查询所有数据
2.example.createCriteria().xxx:创建条件对象,通过andXXX方法为SQL添加查询添加,每个条件之间是and关系
3.example.or().xxx:将之前添加的条件通过or拼接其他条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
public void testMBG() {
try {
InputStream is = Resources.getReResourcesAsStream("mybaits-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().buid(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//查询所有数据
List<Emp> list = mapper.selectByExample(null);


//根据条件查询
EmpExample example = new EmpExample();
example.createCriteria().andEmpNameEqualTo("张三").andAgeCreaterThanOrEqualsTo(20);
list.forEach(emp -> Ststem.out.println(emp));

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

修改的情况
1.updateByPrimaryKey:通过主键进行数据修改,如果某一个值为null,也会将对应的字段改为null
2.updateByPrimaryKeySelective():通过主键进行选择性数据修改,如果某个值为null,则不修改这个字段

分页插件

在SQL语句中,分页的相关参数如下
1.index:当前分页的索引
2.pageSize:每页显示的条数
3.pageNum:当前页的页码
4.index=(pageNum-1)*pageSize

使用方法

1.添加相关依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>

2.在MyBatis的核心配置文件进行相关配置

1
2
3
4
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
<plugins>

3.使用方法
在查询功能之前使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能

  • pageNum:当前页的页码
  • pageSize:每页显示的条数
1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void testPageHelper() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//访问第一页,每页四条数据
PageHelper.startPage(1,4);
List<Emp> emps = mapper.selectByExample(null);
emps.forEach(System.out::println);
}

相关数据

1.直接输出的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void testPageHelper() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//访问第一页,每页四条数据
Page<Object> page = PageHelper.startPage(1, 4);
List<Emp> emps = mapper.selectByExample(null);
//在查询到List集合后,打印分页数据
System.out.println(page);
}

2.使用PageInfo
在查询获取list集合之后,使用PageInfopageInfo = new PageInfo<>(Listlist, intnavigatePages)获取分页相关数据

  • list:分页之后的数据
  • navigatePages:导航分页的页码数
1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void testPageHelper() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
PageHelper.startPage(1, 4);
List<Emp> emps = mapper.selectByExample(null);
PageInfo<Emp> page = new PageInfo<>(emps,5);
System.out.println(page);
}
常用数据

1.pageNum:当前页的页码
2.pageSize:每页显示的条数
3.size:当前页显示的真实条数
4.total:总记录数
5.pages:总页数
6.prePage:上一页的页码
7.nextPage:下一页的页码
8.isFirstPage/isLastPage:是否为第一页/最后一页
9.hasPreviousPage/hasNextPage:是否存在上一页/下一页
10.navigatePages:导航分页的页码数
11.navigatepageNums:导航分页的页码,[1,2,3,4,5]


SSM系列第5篇数据库框架
https://www.eldpepar.com/coding/1180/
作者
EldPepar
发布于
2022年11月16日
许可协议