写在前面: 从2018年底开始学习SpringBoot,也用SpringBoot写过一些项目。现在想对学习Springboot的一些知识总结记录一下。如果你也在学习SpringBoot,可以关注我,一起学习,一起进步。
相关文章:
【Springboot系列】Springboot入门到项目实战
MyBatis-Plus介绍
官网地址:https://mybatis.plus
1、简介
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
2、特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
3、支持数据库
- mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver
- 达梦数据库 、 虚谷数据库 、 人大金仓数据库
表结构设计
1、表结构
设计了一张user用户表,表结构如下。
2、建表
执行以下SQL语句建表
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(32) DEFAULT NULL COMMENT '姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`course` varchar(32) DEFAULT NULL COMMENT '课程',
`fraction` int(11) DEFAULT NULL COMMENT '分数',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4;
3、添加初始数据
执行以下SQL语句添加初始数据。
INSERT INTO `user` VALUES ('1', '张三', '20', 'java', '89');
INSERT INTO `user` VALUES ('2', '李四', '19', 'C', '64');
INSERT INTO `user` VALUES ('3', '王五', '18', 'HTML', '90');
INSERT INTO `user` VALUES ('4', '小熊', '20', 'JavaScript', '76');
INSERT INTO `user` VALUES ('5', '小马', '17', 'C++', '77');
INSERT INTO `user` VALUES ('6', '小李', '18', 'JAVA', '59');
INSERT INTO `user` VALUES ('7', '小王', '18', 'C', '60');
INSERT INTO `user` VALUES ('8', '小张', '18', 'JAVA', '58');
INSERT INTO `user` VALUES ('9', '小白', '23', 'python', '61');
搭建项目
1、项目结构
2、新建Springboot项目
pom.xml文件中需要引入以下依赖。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- mybatisPlus 核心库 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
3、在 application.properties配置文件中添加相关的配置信息
#链接数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/mp?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#mybatis-plus相关配置
#xml扫描,多个目录用逗号或者分号隔离(告诉Mapper 对应的xml文件位置)
mybatis-plus.mapper-locations= classpath:mapper/*.xml
#mybatis别名包扫描,映射类所在的包名,对应实体类的包名
mybatis-plus.type-aliases-package=com.mcy.mp.fristmp.entity
4、在SpringBoot启动类中添加@MapperScan注解
在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹
@SpringBootApplication
@MapperScan(basePackages = {"com.mcy.mp.fristmp.mapper"})
public class FristmpApplication {
public static void main(String[] args) {
SpringApplication.run(FristmpApplication.class, args);
}
}
Mybatis-Plus入门
1、编写实体类
注意: 在此处使用了 Lombok 简化代码,不需要写Get和Set方法。需要在Class 类上面加 @Data注解即可(之前都是使用的Get和Set方法,但看官网添加依赖时添加了,就用的Lombok )。
@Data
@TableName("user") //TableName表名注解,对应数据库的表名
public class User {
/**
* @TableId主键注解,可以设置主键的类型,不写会采取默认值,默认值可以在application.properties配置文件中设置
* AUTO:数据库ID自增
* INPUT: 用户输入ID
* ID_WORKER: 全局唯一ID,Long类型的主键
* ID_WORKER_STR: 字符串全局唯一ID
* UUID: 全局唯一ID,UUID类型的主键
* NONE: 该类型为未设置主键类型
*/
@TableId(type = IdType.AUTO)
private Integer id;
//姓名
private String name;
//年龄
private Integer age;
//科目
private String course;
//分数
private Integer fraction;
}
2、编写Mapper接口
UserMapper.java接口
public interface UserMapper extends BaseMapper<User> {
}
注: Mapper接口需要继承BaseMapper接口,该接口中封装了一些CRUD方法,所以继承该接口后,就不需要编写mapper.xml 文件,即可获得CRUD功能。
3、编写业务层接口
UserService.java接口
public interface UserService extends IService<User> {
}
注: UserService接口需要继承IService接口,该接口进一步封装了CRUD采用get 查询单行 、remove 删除、 list 查询集合、 page 分页、 前缀命名方式区分 Mapper 层避免混淆。
4、编写业务层实现类
UserServiceImpl.java类
@Service
@Transactional //事务
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
5、编写测试Controller
UserController.java类
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 根据id查询用户
* @param id
* @return 用户实体类
*/
@RequestMapping("/findById")
public User findById(Integer id){
User user = userService.getById(id);
return user;
}
/**
* 查询全部信息
* @return 用户集合
*/
@RequestMapping("/findAll")
public List<User> findAll(){
List<User> userList = userService.list();
return userList;
}
/**
* 新增
* @return 提示信息
*/
@RequestMapping("/save")
public String save(){
User user = new User();
user.setName("小三");
user.setAge(18);
user.setCourse("C++");
user.setFraction(88);
userService.save(user);
return "新增一条数据成功!";
}
}
运行项目后,浏览器上测试:
根据id查询用户
查询全部数据
查询方法为IService接口中封装的,常用方法如下。
Save方法
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);
参数说明
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 |
Collection | entityList | 实体对象集合 |
int | batchSize | 插入批次数量 |
SaveOrUpdate方法
// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
参数说明
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 |
Wrapper | updateWrapper | 实体对象封装操作类 UpdateWrapper |
Collection | entityList | 实体对象集合 |
int | batchSize | 插入批次数量 |
Remove方法
// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);
参数说明
类型 | 参数名 | 描述 |
---|---|---|
Wrapper | queryWrapper | 实体包装类 QueryWrapper |
Serializable | id | 主键ID |
Map<String, Object> | columnMap | 表字段 map 对象 |
Collection<? extends Serializable> | idList | 主键ID列表 |
Update方法
// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereEntity 条件,更新记录
boolean update(T entity, Wrapper<T> updateWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);
参数说明
类型 | 参数名 | 描述 |
---|---|---|
Wrapper | updateWrapper | 实体对象封装操作类 UpdateWrapper |
T | entity | 实体对象 |
Collection | entityList | 实体对象集合 |
int | batchSize | 更新批次数量 |
Get方法
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
参数说明
类型 | 参数名 | 描述 |
---|---|---|
Serializable | id | 主键ID |
Wrapper | queryWrapper | 实体对象封装操作类 QueryWrapper |
boolean | throwEx | 有多个 result 是否抛出异常 |
T | entity | 实体对象 |
Function<? super Object, V> | mapper | 转换函数 |
List方法
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
参数说明
类型 | 参数名 | 描述 |
---|---|---|
Wrapper | queryWrapper | 实体对象封装操作类 QueryWrapper |
Collection<? extends Serializable> | idList | 主键ID列表 |
Map<?String, Object> | columnMap | 表字段 map 对象 |
Function<? super Object, V> | mapper | 转换函数 |
Page方法
// 无条件翻页查询
IPage<T> page(IPage<T> page);
// 翻页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件翻页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 翻页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
参数说明
类型 | 参数名 | 描述 |
---|---|---|
IPage | page | 翻页对象 |
Wrapper | queryWrapper | 实体对象封装操作类 QueryWrapper |
分页
1、创建分页配置类
MybatisPlusConfig.java类
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
2、编写分页测试方法
在上方的测试Controller中添加分页测试方法,代码如下
/**
* 分页查询
* @return 当前页数据
*/
@RequestMapping("/findAllPage")
public IPage<User> findAllPage(){
//需要在Config配置类中配置分页插件
IPage<User> page = new Page<>();
page.setCurrent(1); //当前页
page.setSize(3); //每页条数
page = userService.page(page);
long current = page.getCurrent(); // 当前页
long pages = page.getPages();// 总页数
long total = page.getTotal();// 总记录数
long size = page.getSize();// 每页记录数
System.out.println("当前页:" + current);
System.out.println("总页数:" + pages);
System.out.println("总记录数:" + total);
System.out.println("每页记录数:" + size);
return page;
}
在浏览器中测试
控制台输出
Mybatis-Plus的条件构造器
当查询条件复杂的时候,我们可以使用Mybatis-Plus的条件构造器,可以查看官方文档:MyBatis-Plus的条件构造器
1、测试方法
在上方的测试Controller中添加分页测试方法,代码如下
/**
* mybatis-plue条件构造器
* @return 查询数据
*/
@RequestMapping("/findByFractionGt80")
public List<User> findByFractionGt80(){
//定义条件构造器
QueryWrapper<User> qw = new QueryWrapper<>();
qw.lambda().gt(User::getFraction, 80);
List<User> userList = userService.list(qw);
return userList;
}
上述代码中,添加条件时,使用的是Lambda表达式。
在浏览器中测试,查询分数大于80的数据,结束如下:
2、条件构造器的常用方法
条件构造器的常用方法
查询方式 | 方法说明 |
---|---|
setSqlSelect | 设置 SELECT 查询字段 |
where | WHERE 语句,拼接 + WHERE 条件 |
and | AND 语句,拼接 + AND 字段=值 |
or | OR 语句,拼接 + OR 字段=值 |
eq | 等于= |
allEq | 基于 map 内容等于= |
ne | 不等于<> |
gt | 大于> |
ge | 大于等于>= |
lt | 小于< |
le | 小于等于<= |
like | 模糊查询 LIKE |
notLike | 模糊查询 NOT LIKE |
in | IN 查询 |
notIn | NOT IN 查询 |
isNull | NULL 值查询 |
isNotNull | IS NOT NULL |
groupBy | 分组 GROUP BY |
having | HAVING 关键词 |
orderBy | 排序 ORDER BY |
orderByAsc | ASC 排序 ORDER BY |
orderByDesc | DESC 排序 ORDER BY |
exists | EXISTS 条件语句 |
notExists | NOT EXISTS 条件语句 |
between | BETWEEN 条件语句 |
notBetween | NOT BETWEEN 条件语句 |
addFilter | 自由拼接 SQL |
last | 拼接在最后,例如:last(“LIMIT 1”) |
自定义SQL
使用Mybatis-Plus时不符对原有的Mybatis架构产生任何影响,而且Mybatis-Plus支持所有Mybatis原生的特性。有时候由于项目需求,可能需要自己写一些复杂的SQL语句,这里来看一下一个简单的自定义SQL案例吧!
1、编写Mapper.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.mcy.mp.fristmp.mapper.UserMapper">
<!--根据分数动态查询,查询大于条件分数的数据-->
<select id="selectUserFraction" resultType="User" parameterType="User">
select * from user where fraction > #{fraction}
</select>
</mapper>
2、在UserMapper接口中添加自定义方法
public interface UserMapper extends BaseMapper<User> {
/**
* 查询大于该分数的学生
* @param fraction 分数
* @return 查询结构
*/
List<User> selectUserFraction(Integer fraction);
}
3、在UserService接口中添加自定义方法
public interface UserService extends IService<User> {
/**
* 查询大于该分数的学生
* @param fraction 分数
* @return 查询结构
*/
List<User> selectUserFraction(Integer fraction);
}
4、在UserServicelmpl类中重写方法
@Service
@Transactional //事务
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> selectUserFraction(Integer fraction) {
return userMapper.selectUserFraction(fraction);
}
}
5、测试方法
在上方的测试Controller中添加分页测试方法,代码如下
/**
* 自定义SQL 查询大于该分数的学生
* @param fraction 分数
* @return
*/
@RequestMapping("/selectUserFraction")
public List<User> selectUserFraction(Integer fraction){
List<User> userList = userService.selectUserFraction(fraction);
return userList;
}
浏览器测试结果:
有什么不足之处,欢迎大家指出,期待与你的交流。