个人博客网:https://wushaopei.github.io/ (你想要这里多有)
目录
一、MyBatis-Plusd的 简介及特性:
1、简介:
2、特性介绍:
二、lombok简介及安装
三、Mybatis-Plus 的使用准备
1、创建新的 maven 工程,并在 application.yml中配置数据库连接
2、创建实体类User 和对应数据库表
3、创建原始 Mapper 类并继承通用 Mapper
4、在启动类中添加 mapper 的包扫描路径
5、配置pom.xml
四、Mybatis-Plus 的基本使用
1、通用mapper新增方法
2、常用注解
3、排除非表字段的三种方式
五、Mybatis-Plus 查询方法
1、普通查询
2、条件构造器查询
3、Select 不列出全部字段
4、condition作用
5、实体作为条件构造器构造方法的参数
6、AllEq用法
7、其他使用条件构造器的方法
8、lambda条件构造器
六、自定义 sql
1、在 application.yml 中 配置映射文件地址:
2、第一种:
3、第二种:
七、分页查询
1、分页插件配置类: 创建 MybatisPlusConfig类,注入到 Spring中进行管理
2、分页查询的两种方式:
八、更新与删除
1、更新方法
2、删除方法
九、ActiveRecord 模式
AR模式的使用需要满足两个条件,如下:
条件1:必须存在对应的原始mapper并继承Model 泛型类,并配置相应类注解,
条件2: 在 mapper 接口 中要 继承 BaseMapper 泛型类
它在Mybatis 的基础上进行加强,不对Mybatis 做结构性改变,有利于提高基于MyBatis 的项目开发效率
特性一:
- 无侵入、损耗少、强大的CRUD 操作
- 支持Lambda 形式调用、支持多种数据库
- 支持主键自动生成、支持ActiveRecord模式
特性二:
- 支持自定义全局通用操作、支持关键词自动转义
- 内置代码生成器、内置分页插件、内置性能分析插件
- 内置全局拦截插件、内置sql 注入剥离器
Lombok 会在编译时加入 GET/SET 、hashcode 等方法,其生成的方法会根据当前被标记的javabean属性的注解等动态生成,避免手动生成GET/SET方法时,当属性需求发生变化删改时 频繁的 修改 javabean中的GET/SET 、EQUALS等带来不必要的工作量 ;有利于提高开发的效率
配置数据库和日志输出
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3333/mp?useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
logging:
level:
root: warn
com.mp.dao: trace
pattern:
console: '%p%m%n'
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
public class User extends Model{
private Long id;
//用户名
private String name;
//年龄
private Integer age;
//邮箱
private String email;
//管理id
private Long managerId;
//创建时间
private LocalDateTime createTime;
}
因为使用了lombok插件,因此不需要手动创建 GET/SET 方法以及 hashcode等方法,前面已经做过解释。
public interface UserMapper extends BaseMapper{
}
@SpringBootApplication
@MapperScan("com.mp.dao")
public class Bootstrap
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
org.springframework.boot
spring-boot-starter-parent
2.1.3.RELEASE
UTF-8
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
true
com.baomidou
mybatis-plus-boot-starter
3.1.0
mysql
mysql-connector-java
junit
junit
3.8.1
test
- 包含: 新增方法、常用注解、排除非表字段的三种方式
package com.mp;
@RunWith(SpringRunner.class)
@SpringBootTest
public class InsertTest {
@Autowired
private UserMapper userMapper;
@Test
public void insert() {
User u = new User();
u.setId(1168737089097060324L);
u.setName("陈庆");
u.setAge(22);
u.setEmail("[email protected]");
u.setManagerId(1088248166370832385L);
u.setCreateTime(LocalDateTime.now());
u.setRemark("我是一个备注信息");
User.setPostil("我是批注");
int rows = userMapper.insert(u);
System.out.print("影响记录数"+ rows +"条");
}
}
当userMapper调用insert方法时,其实际上并不需要我们编写SQL 语句,而是交由通用Mapper调用其封装的方法:
从而实现映射关系,执行数据的插入。
控制台执行结果:
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.1.0
DEBUG==> Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
DEBUG==> Parameters: 1168737089097060324(Long), 陈庆(String), 22(Integer), [email protected](String)
DEBUG<== Updates: 1
影响记录数1条
由以上结果,可知,当通用Mapper进行映射执行插入请求时,其底层进行了SQL语句 的编码生成
(1)@TableName("表名")
当表名为 mp_user 时,在不改变 实体类的名字的情况下,通过添加 @TableName(“表名mp_user”)的方式来指定对应的数据库表名,以此解决在不编写sql语句的情况下,实体类的名字与数据库表名不一致而导致无法进行表操作的问题。
@Data
@TableName("mp_user") //此注解用于标识当前实体类所对应的表,编译时生效
public class User{
.....................
}
@Test测试结果:
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.1.0
DEBUG==> Preparing: INSERT INTO mp_user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
DEBUG==> Parameters: 1168737089092060324(Long), 陈庆(String), 22(Integer), [email protected](String)
DEBUG<== Updates: 1
影响记录数1条
(2)@TableField("表字段名")
private Long id;
//用户名
@TableField("name")//当前注解用于指定属性对应的表字段
// private String name;
private String username;
//年龄
@Test测试结果;
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.1.0
DEBUG==> Preparing: INSERT INTO mp_user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
DEBUG==> Parameters: 1168732089092060324(Long), 陈庆(String), 22(Integer), [email protected](String)
DEBUG<== Updates: 1
影响记录数1条
由结果可知:使用 @TableField("name")来直接指定 user 实体类中某一个属性所对应的数据库表中的哪一列
(3)@TableId
当前注解用于标注 javabean 中哪个字段是 主键 id
//主键
@TableId //主键策略
private Long id;
(1)第一种: 添加 transient
说明:
//备注
private transient String Remark;
@Test测试方法:
u.setRemark("我是一个备注信息");
User.setPostil("我是批注");
int rows = userMapper.insert(u);
执行结果:
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.1.0
DEBUG==> Preparing: INSERT INTO mp_user ( id, name, age, email, manager_id, create_time ) VALUES ( ?, ?, ?, ?, ?, ? )
DEBUG==> Parameters: 1268732089092060324(Long), 陈庆(String), 22(Integer), [email protected](String), 1168737089097060354(Long), 2019-09-03 16:22:38.945(Timestamp)
DEBUG<== Updates: 1
影响记录数1条
(2)第二种: 使用 static
说明:
//批注
private static String Postil;
public static void setPostil(String Postil) {
Postil = Postil;
}
public static String getPostil() {
return Postil;
}
@Test测试方法:
User.setPostil("我是批注");
int rows = userMapper.insert(u);
执行结果:
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.1.0
DEBUG==> Preparing: INSERT INTO mp_user ( id, name, age, email, manager_id, create_time ) VALUES ( ?, ?, ?, ?, ?, ? )
DEBUG==> Parameters: 1263732089092060324(Long), 陈庆(String), 22(Integer), [email protected](String), 1168737089097060354(Long), 2019-09-03 16:22:38.945(Timestamp)
DEBUG<== Updates: 1
影响记录数1条
(3)第三种: 使用 @TableField(exist=false)
说明:
@TableField(exist=false)
private transient String Remark;
测试结果:
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.1.0
DEBUG==> Preparing: INSERT INTO mp_user ( id, name, age, email, manager_id, create_time ) VALUES ( ?, ?, ?, ?, ?, ? )
DEBUG==> Parameters: 1263732089192060324(Long), 陈庆(String), 22(Integer), [email protected](String), 1168737089097060354(Long), 2019-09-03 16:22:38.945(Timestamp)
DEBUG<== Updates: 1
影响记录数1条
@RunWith(SpringRunner.class)
@SpringBootTest
public class RetrieveTest {
@Autowired
private UserMapper userMapper;
//根据单个id查询用户
// @Test
public void selectBy() {
User user = userMapper.selectById(1168440364299722753L);
System.out.println(user);
}
//根据 id 的 List 查询多个用户
// @Test
public void selectIds() {
List idsList = Arrays.asList(1168440364299722753L,1094592041087729666L,1094590409767661570L);
List userList = userMapper.selectBatchIds(idsList);
userList.forEach(System.out::println);
}
//根据 map 的 key-value 中的属性和值 查询 用户
// @Test
public void selectByMap() {
//map.put("name","王天风")
//map.put("age",30)
//where namem = "王天风" and age = 30
Map columnMap = new HashMap();
columnMap.put("name", "王天风");
columnMap.put("age", 25);
List userList = userMapper.selectByMap(columnMap);
userList.forEach(System.out::println);
}
使用 QueryWrapper<>(); 的实例来创建 sql ,通过 拼接 like 进行模糊查询,使用 lt 进行小于 的判断
/*
* 1、名字中包含与并且年龄小于40
* name like `%雨%` and age <40
* */
// @Test
public void selectByWrapper() {
QueryWrapper queryWrapper = new QueryWrapper();
// QueryWrapper queryWrapper = Wrappers.query();
queryWrapper.like("name", "雨").lt("age",40);
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
* 2、名字中包含雨 并且年龄大于等于20 且小于等于40 并且email 不为空
* name like `%雨%`` and age between 20 and 40 and email is not null
* */
// @Test
public void selectByWrapper2() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.like("name", "雨").between("age", 20, 40).isNotNull("email");
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
* 名字为王姓或者年龄大于等于25,按照年龄降序排列,年龄相同按照 id 升序排列
* name like `王%` or age>=40 order by age desc id asc
* */
// @Test
public void selectByWrapper3() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.likeRight("name", "王").or().ge("age",25).orderByDesc("age")
.orderByDesc("id");
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
* 4、创建日期为 2019年2月14日 并且质数上级为名字为王姓
* date_format(create_time,'%Y-%m-%d') and manager_id
* in (select id from user where name like '王%' )
* */
// @Test
public void selectByWrapper4() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.apply("date_format(create_time,'%Y-%m-%d')={0}","2019-02-14 " )
// queryWrapper.apply("date_format(create_time,'%Y-%m-%d')={2019-02-14" ) //当前行与上一行效果是一样的,但是当前行存在SQL注入的风险,如下列行
// queryWrapper.apply("date_format(create_time,'%Y-%m-%d')=2019-02-14 or true or true" ) // 当前行存在SQL 注入的风险,在日期时间末尾添加了or true or true 后会见所有的结果都查询出来,会让用户看到不该看到的东西
.inSql("manager_id", "select id from mp_user where name like '王%'");
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
* 5、名字为王姓并且 (年龄小于40或邮箱不为空)
* name like '王%' and (age<40 or email is not null)
* */
// @Test
public void selectByWrapper5() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.likeRight("name", "王").and(wq->wq.lt("age",40).or().isNotNull("email"));
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
* 6、名字为王姓或者(年龄小于40 并且年龄大于20 并且 邮箱不为空)
* name like'王%' or (age <40 and age>20 and email is notNull)
* */
// @Test
public void selectByWrapper6() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.likeRight("name", "王").or(wq->wq.lt("age", 40).gt("age",20)
.isNotNull("email"));
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
* 7、(年龄小于40或邮箱不为空) 并且名字为王姓
* (age<40 or email is not null) and name like '王%'
* */
// @Test
public void selectByWrapper7() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.nested(wq->wq.lt("age", 40).or().isNotNull("email")
.likeRight("name", "王"));
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
* 8、年龄为 30、31、34、35
* age in (30、31、34、35)
* */
// @Test
public void selectByWrapper8() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.in("age", Arrays.asList(30,31,34,35)).last("limit 1");
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/*
* 1、名字中包含雨并且年龄小于40
* name like '%雨%' and age<40
* */
// @Test
public void selectByWrapperSupper() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.select("id","name").like("name", "雨").lt("age", 40)
.select(User.class,info->!info.getColumn().equals("create_time")&&
!info.getColumn().equals("manager_id"));
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
// @Test
public void testCondition() {
String name = "王";
String email = "";
condition(name,email);
}
private void condition(String name,String email) {
QueryWrapper queryWrapper = new QueryWrapper();
// if(StringUtils.isNotEmpty(name)) {
// queryWrapper.like("name", name);
// }
// if(StringUtils.isNotEmpty(email)) {
// queryWrapper.like("email", email);
// }
queryWrapper.like(StringUtils.isNotEmpty(name), "name",name)
.like(StringUtils.isNotEmpty(email), "email",email);
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
@Test
public void selectByWrapperEntity() {
User whereUser = new User();
whereUser.setName("刘红雨");
whereUser.setAge(32);
QueryWrapper queryWrapper = new QueryWrapper(whereUser);
// queryWrapper.like("name", "雨").lt("age",40);
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
@Test
public void selectByWrapperAllEq() {
QueryWrapper queryWrapper = new QueryWrapper();
Map params = new HashMap();
params.put("name", "王天风");
params.put("age", 25);
queryWrapper.allEq(params);
List userList = userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
@Test
public void selectByWrapperMaps() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.like("name","雨").lt("age",40);
List
@Test
public void selectLambda() {
LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery();
lambdaQuery.like(User::getName, "雨").lt(User::getAge, 40);
//where name like '%雨'
List userList = userMapper.selectList(lambdaQuery);
userList.forEach(System.out::println);
}
/*
* 5、名字为王姓并且(年龄小于40 或邮箱不为空)
* name like '王%' and (age<40 or email is not null)
*
* */
@Test
public void selectLambda2() {
LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery();
lambdaQuery.likeRight(User::getName, "王")
.and(lqw->lqw.lt(User::getAge,40).or().isNotNull(User::getEmail));
List userList = userMapper.selectList(lambdaQuery);
userList.forEach(System.out::println);
}
自定义SQL的两种方式:
mybatis-plus:
mapper-locations:
- com/mp/mapper/*
public interface UserMapper extends BaseMapper{
@Select("select * from user ${ew.customSqlSegment}")
List selectAll(@Param(Constants.WRAPPER) Wrapper wrapper);
}
需要创建映射文件 UserMapper.xml
@Test
public void selectMy() {
LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery();
lambdaQuery.likeRight(User::getName, "王")
.and(lqw->lqw.lt(User::getAge, 40).or().isNotNull(User::getEmail));
List userList = userMapper.selectAll(lambdaQuery);
userList.forEach(System.out::println);
}
简介: Mybatis-Plus 提供了一个物理分页的插件
package com.mp.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
方式一:使用userMapper.selectPage(page,data);返回结果为 实体类 javabean
@Test
public void selectPage() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.ge("age",22);
Page page = new Page(1,3);
IPage iPage = userMapper.selectPage(page,queryWrapper);
System.out.println("总页数"+iPage.getPages());
System.out.println("总记录数" + iPage.getTotal());
List userList = iPage.getRecords();
userList.forEach(System.out::println);
}
方式二:使用userMapper.selectPage(page,data);返回结果为 Map
@Test
public void selectPage2() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.ge("age",26);
Page page = new Page(1,2);
IPage> iPage = userMapper.selectMapsPage(page, queryWrapper);
System.out.println("总页数"+iPage.getPages());
System.out.println("总记录数" + iPage.getTotal());
List> userList = iPage.getRecords();
userList.forEach(System.out::println);
}
方式三: 自定义分页查询方法,可实现多表联合查询返回分页数据
创建 自定义方法 :
IPage selectUserPage(Page page,@Param(Constants.WRAPPER) Wrapper wrapper);
UserMapper.xml
测试方法:
@Test
public void selectMyPage3() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.ge("age",26);
Page page = new Page(1,2);
IPage iPage = userMapper.selectUserPage(page, queryWrapper);
System.out.println("总页数"+iPage.getPages());
System.out.println("总记录数" + iPage.getTotal());
List userList = iPage.getRecords();
userList.forEach(System.out::println);
}
package com.mp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mp.dao.UserMapper;
import com.mp.entity.User;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UpdateTest {
@Autowired
private UserMapper userMapper;
@Test
public void updateById() {
User user = new User();
user.setId(1168443892250533890L);
user.setAge(26);
user.setEmail("[email protected]");
int rows = userMapper.updateById(user);
System.out.println("影响记录数:" + rows + "条");
}
@Test
public void updateByWrapper() {
UpdateWrapper updateWrapper = new UpdateWrapper();
updateWrapper.eq("name", "李艺伟").eq("age", 28);
User user = new User();
user.setEmail("[email protected]");
user.setAge(29);
int rows = userMapper.update(user, updateWrapper);
System.out.println("影响记录数:" + rows + "条");
}
@Test
public void updateByWrapperLambda() {
LambdaUpdateWrapper lambdaUpdate = new LambdaUpdateWrapper();
lambdaUpdate.eq(User::getName, "李艺伟").eq(User::getAge,29).set(User::getAge, 31);
int rows = userMapper.update(null, lambdaUpdate);
System.out.println("影响记录数: " + rows);
}
}
package com.mp;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mp.dao.UserMapper;
import com.mp.entity.User;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DeleteTest {
@Autowired
private UserMapper userMapper;
@Test
public void deleteById() {
int rows = userMapper.deleteById(1168439950892429314L);
System.out.println("影响记录数:"+ rows +"条");
}
@Test
public void deleteByMap() {
Map columnMap = new HashMap<>();
columnMap.put("name", "向后");
columnMap.put("age", 25);
int rows = userMapper.deleteByMap(columnMap);
System.out.println("删除条数:" + rows + "条");
}
@Test
public void deleteBatchIds() {
int rows = userMapper.deleteBatchIds(Arrays.asList(1168440364299722753L,1168444966134968322L));
System.out.println("删除条数:" +rows);
}
@Test
public void deleteByWrapper() {
LambdaQueryWrapper lambdaQuery = Wrappers.lambdaQuery();
lambdaQuery.eq(User::getAge, 34).or().gt(User::getAge, 41);
int rows = userMapper.delete(lambdaQuery);
System.out.println("删除条数:" + rows);
}
}
同时申明序列号 serialVersionUID = 1L
@Data
@TableName("mp_user")
@EqualsAndHashCode(callSuper=false)
public class User extends Model{
private static final long serialVersionUID = 1L;
//主键
private Long id;
package com.mp.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mp.entity.User;
public interface UserMapper extends BaseMapper{
}
代码:https://github.com/wushaopei/MyBatis/tree/master/first-CRUD