1. mybatis-plus?
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
mybatis-plus官网: https://baomidou.com
2. 引入依赖
引入mybatis-plus的第三方stater以及数据源:
<!-- mybatis-plus stater -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!-- druid数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
3. 编写配置文件
在application.yaml中配置数据源的相关配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/phpdemo?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
4. 编写sql表
编写测试用例的sql表:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '姓名',
`age` int(0) NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'Jone', 18, 'test1@baomidou.com');
INSERT INTO `user` VALUES (2, 'Jack', 20, 'test2@baomidou.com');
INSERT INTO `user` VALUES (3, 'Tom', 28, 'test3@baomidou.com');
INSERT INTO `user` VALUES (5, 'Billie', 24, 'test5@baomidou.com');
INSERT INTO `user` VALUES (6, '叶秋', 18, 'robindebug@163.com');
INSERT INTO `user` VALUES (7, '张三', 49, 'zhangsan@126.com');
SET FOREIGN_KEY_CHECKS = 1;
5. mapper层
5.1 mybatis-plus做了什么?及创建mapper接口
在springboot中使用mybatis-plus创建mapper接口,可以通过继承baseMapper类来快速生成常用的sql(baseMapper类为我们提供了很便捷的sql,懒人必备哈哈哈)
mapper接口:
package com.robin.boot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.robin.boot.bean.User;
import org.apache.ibatis.annotations.Mapper;
/**
* 使用mapper接口继承BaseMapper的方式,可以快速获得常用的sql
* 无须编写mapper.xml文件
*/
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
注意mybatis-plus为我们自动配置了以下内容:
- MybatisPlusAutoConfiguration 配置类,MybatisPlusProperties 配置项绑定。mybatis-plus:xxx 就是对mybatis-plus的定制
- SqlSessionFactory 自动配置好。底层是容器中默认的数据源
- mapperLocations 自动配置好的。有默认值。classpath*:/mapper/**/*.xml;任意包的类路径下的所有mapper文件夹下任意路径下的所有
xml都是sql映射文件。 建议以后sql映射文件,放在 mapper下 - 容器中也自动配置好了 SqlSessionTemplate
- @Mapper 标注的接口也会被自动扫描;
相比mybatis的整合,这次我们连创建xml也不需要了,它已经自动默认好了。
5.2 baseMapper源码
baseMapper源码:
/*
* Copyright (c) 2011-2020, baomidou (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.baomidou.mybatisplus.core.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
* <p>这个 Mapper 支持 id 泛型</p>
*
* @author hubin
* @since 2016-01-23
*/
public interface BaseMapper<T> extends Mapper<T> {
/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,删除记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
/**
* 查询(根据 columnMap 条件)
*
* @param columnMap 表字段 map 对象
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
/**
* 根据 entity 条件,查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}
baseMapper中为我们提供了很多常用的sql方法,只要通过mapper接口继承该接口即可"开箱即用"。
6. service层及controller层
6.1 service层
service层接口:
package com.robin.boot.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.robin.boot.bean.User;
public interface UserService extends IService<User> {
}
serviceImpl实现类:
package com.robin.boot.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.robin.boot.bean.User;
import com.robin.boot.mapper.UserMapper;
import com.robin.boot.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
6.2 controller层
编写controller及请求映射处理:
package com.robin.boot.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.robin.boot.bean.User;
import com.robin.boot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class UserController {
@Autowired
UserService userService;
// 分页查询用户
@GetMapping("/showUser")
public String dynamic_table(@RequestParam(value = "pn",defaultValue = "1")Integer pn, Model model){
// 分页查询
Page<User> userPage = new Page<>(pn,3);
// 分页查询结果
IPage<User> page = userService.page(userPage,null);
model.addAttribute("users",page);
return "show";
}
// 单个用户删除
@GetMapping("/user/delete/{id}")
public String deleteUser(@PathVariable("id") Long id,
@RequestParam(value = "pn",defaultValue = "1") Integer pn){
userService.removeById(id);
return "redirect:/showUser?pn="+pn;
}
}
6.2.1 page对象
7. 分页插件的使用
我们查看其官网介绍: https://baomidou.com/plugins/pagination/
MybatisPlusInterceptor是核心插件,目前代理了 Executor#query 和 Executor#update 和 StatementHandler#prepare 方法。
mybatis-plus中的所有插件都是基于InnerInterceptor这个接口来实现插件功能。
官方提供的分页插件参考配置文件如下:
@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
}
创建config包我们自定义配置类,使用mybatis-plus的插件:
package com.robin.boot.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfig {
/**
* mybatis-plus 分页插件
* @return
*/
@Bean
public MybatisPlusInterceptor paginationInnerInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
return mybatisPlusInterceptor;
}
}
8. 数据显示html页面
使用thymeleaf模板引擎来获取数据和数据遍历,以及视图渲染:
show.html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户数据显示页面</title>
<style>
table,tr,td{
border: 1px solid deepskyblue;
}
table{
margin: 0 auto;
}
h3{
text-align: center;
}
.recordsBar{
text-align: center;
}
a{
color: black;
}
.active>a{
color: red;
}
</style>
</head>
<body>
<h3>用户信息</h3>
<hr>
<table>
<tr>
<td>id</td>
<td>姓名</td>
<td>年龄</td>
<td>邮箱</td>
<td>操作</td>
</tr>
<tr th:each="user:${users.records}">
<td th:text="${user.id}">xxxx</td>
<td th:text="${user.name}">xxxx</td>
<td th:text="${user.age}">xxxx</td>
<td th:text="${user.email}">xxxx</td>
<td><a th:href="@{/user/delete/{id}(id=${user.id},pn=${users.current})}">删除</a></td>
</tr>
</table>
<hr>
<div class="recordsBar">
<span>当前第 [[${users.current}]] 页</span>
<span>共 [[${users.pages}]] 页</span>
<span>总记录数 [[${users.total}]] 条</span>
<span th:class="${num == users.current ?'active':''}" th:each="num : ${#numbers.sequence(1,users.pages)}">
<a th:href="@{/showUser(pn=${num})}" th:text="${num}">1</a>
</span>
</div>
</body>
</html>
9. 项目结构及整合测试
9.1 项目结构
9.2 运行测试
访问localhost:8080/showUser
,分页查询用户首页
点击页码跳转
测试删除:
删除后,还是在同页面
总结
mybatis-plus是mybatis功能的增强版,我们使用的话,也是引入对应的stater即可,相比mybatis更方便,无需指定配置mapper.xml(前提是mapper接口是使用继承baseMapper接口的方式),mybatis-plus提供了baseMapper接口类,我们可以使用自己的mapper接口去继承,可以快速的无需自己编写sql方法,baseMapper接口里面提供了丰富的方法。
mybatis-plus提供了很多插件,可以去其官网查看如何使用。