Mybatis-Plus(简称MP),是Mybatis框架的增强版,在不改变Mybatis原有功能的基础上进行功能增强,目标是为了简化开发,提升效率效率。官网地址:MyBatis-Plus (baomidou.com)
tips:因为IDEA还未引入MP的依赖选项,因此MP的坐标需要在工程创建以后手动引入,mysql坐标可以在创建工程时进行勾选引入。
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.1version>
dependency>
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?ServerTime=UTC
username: root
password: root
public class User {
private int id;
private String username;
private Integer age;
private String sex;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
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;
}
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ht.domain.User;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ht.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class MybatisplusLearningApplicationTests {
@Autowired
private UserMapper userMapper;
//增加
/**
* int insert (T t)
* 参数解释:
* T:泛型,用来新增保存的对象数据
* int:返回值,新增成功返回为1,新增失败返回为0
*
*/
@Test
void testSave(){
//1.定义一个新的User对象,并对属性赋值
User user = new User();
user.setUsername("zhangsan");
user.setAge(21);
user.setSex("男");
//2.调用userMapper中的方法向数据库中进行插入
userMapper.insert(user);
}
//删除
/**
* int deleteById (Serializable id)
* 参数解释:
* Serializable:Serializable是String和Number的父类,Number是Integer,Float,Double的父类,因此Serializable
* 类似于我们用Object类型用来接收任意类型的对象一样
* int:返回值,新增成功返回为1,新增失败返回为0
*
* int deleteById (T t)
* 参数解释:
* T:泛型,用来需要删除的对象数据,因为是根据ID值进行删除,所以对象属性值中需要包含ID值
* int:返回值,新增成功返回为1,新增失败返回为0
*/
@Test
void testDelete(){
//1.根据id进行删除
userMapper.deleteById(2);
//2.根据指定对象进行删除
User user = new User();
user.setUsername("zhangsan");
user.setAge(21);
user.setSex("男");
userMapper.deleteById(user);
}
//查找
/**
* T selectById (Serializable id)
* 参数解释:
* T:根据ID查询返回的一条查询对象
* Serializable:解释参照上面,为主键
*
* List selectList(Wrapper queryWrapper)
* 参数解释:
* Wrapper:用来构建条件查询的条件,没有可直接传为Null,默认返回所有
* List:查询的结果是一个对象集合
*/
@Test
void testSearch(){
//根据id进行查找
User user = userMapper.selectById(2);
//查找所有
List<User> users = userMapper.selectList(null);
System.out.println(users);//[User{username='ttttt', age=22, sex='男'}, User{username='ttttt', age=22, sex='男'}, User{username='ttttt', age=22, sex='男'}, User{username='ttttt', age=22, sex='男'}, User{username='zhangsan', age=21, sex='男'}]
}
//修改
/**
* T selectById (Serializable id)
* 参数信息:
* T:需要修改的数据内容,注意因为是根据ID进行修改,所以传入的对象中需要有ID属性值
* Serializable:解释参照上面,为主键
*/
@Test
void testUpdate(){
User user = new User();
user.setUsername("zhangsan");
user.setSex("女");
user.setAge(23);
//根据ID进行修改
userMapper.updateById(user);
}
//分页查询
/**
* IPage selectPage(IPage page, Wrapper queryWrapper)
* 参数解释:
* IPage:返回值
* IPage:用于构建分页查询的条件
* Wrapper:用于构建条件查询的条件
*
*/
@Test
void testPage(){
//1.创建IPage分页对象,设置分页参数,1为当前页码,2为每页的记录数
//IPage是一个接口,因此需要new它实现类,只有一个Page类
IPage<User> page = new Page<>(1,2);
//2.执行分页查询
userMapper.selectPage(page, null);
//3.查询不同结果
System.out.println("当前的页面:"+page.getCurrent());//当前的页面:1
System.out.println("页数:"+page.getSize());//页数:2
System.out.println("数据数:"+page.getRecords());//数据数:[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}]
System.out.println("一共多少页:"+page.getPages());//一共多少页:3
System.out.println("一共多少条数据:"+page.getTotal());//一共多少条数据:5
}
}
注意:想要分页查询生效,需要配置一个分页拦截器MybatisPlusInterceptor(MP已经提供好了),并注入Spring容器,创建过程在下面
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 MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//1.创建MyBatisInterceptor对象
MybatisPlusInterceptor mybatisPlusInterceptor1 = new MybatisPlusInterceptor();
//2.添加分页拦截器,如需添加其它拦截器,可直接添加下面语句
// mybatisPlusInterceptor1.addInnerInterceptor(new 所需拦截器类名);
mybatisPlusInterceptor1.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor1;
}
}
增删改查中,查询功能是比较复杂而且非常重要的,详细解释一下
Mybatis-Plus将复杂的sql语句进行了封装,使用编程的方式就完成条件查询中条件组和,达到了简化开发的目的,用于构建查询条件的类为Wrapper类,上文已经作为参数出现过。
重点来了,Wrapper类怎样来进行条件的构建呢?一般常用的为QueryWrapper和LambdaWrapper
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wW8HtRrK-1659333705447)(C:\Users\if shining\AppData\Roaming\Typora\typora-user-images\image-20220801091722795.png)]
//使用QueryWrapper
@Test
void testConditionSearch(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//生成的sql语句:SELECT username,age,sex FROM user WHERE (age > ?)
//gt:<
queryWrapper.gt("age",23);
List<User> users = userMapper.selectList(queryWrapper);
System.out.println(users);//[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=23, sex='男'}]
}
//使用LambdaWrapper
@Test
void testConditionSearch2(){
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.gt(User::getAge,23);
List<User> user1 = userMapper.selectList(lambdaQueryWrapper);
System.out.println(user1);//[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=23, sex='男'}]
}
注意: 使用QueryWrapper可能出现字段名写错的情况,如age写成aeg,导致查询失败,而且不容易发现,使用LambdaWrapper,为lambda表达式中的,类名::方法名,这样不会出现字段名出现错误的信息。构建LambdaQueryWrapper的时候泛型不能省。
在查询中,上述两种方式,任意哪一种都可以使用,上面都是单条件,现在我们开始使用多条件
//案例1:查询user表中年龄在21-25岁的用户信息
@Test
void testConditionSearch3(){
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.gt(User::getAge,21);
lambdaQueryWrapper.lt(User::getAge,25);
List<User> users = userMapper.selectList(lambdaQueryWrapper);
System.out.println(users);//[User{username='zhangsan', age=23, sex='男'}]
}
也可以使用链式编程
@Test
void testConditionSearch5(){
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.gt(User::getAge,21).lt(User::getAge,25);
List<User> users = userMapper.selectList(lambdaQueryWrapper);
System.out.println(users);//[User{username='zhangsan', age=23, sex='男'}]
}
//案例2:查询数据库表中,年龄小于21或年龄大于24的数据
//or():相当于sql语句中的or关键字,不加默认是and
@Test
void testConditionSearch6(){
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//生成的sql语句: SELECT username,age,sex FROM user WHERE (age > ? OR age < ?)
lambdaQueryWrapper.gt(User::getAge,21).or().lt(User::getAge,25);
List<User> users = userMapper.selectList(lambdaQueryWrapper);
System.out.println(users);//[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='aaa', age=25, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=23, sex='男'}]
}
or():相当于sql语句中的or关键字,不加默认是and
@Test
void testConditionSearch7(){
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//生成的sql语句:SELECT username,age FROM user
lambdaQueryWrapper.select(User::getUsername,User::getAge);
List<User> users = userMapper.selectList(lambdaQueryWrapper);
System.out.println(users);//[User{username='zhangsan', age=21, sex='null'},User{username='zhangsan', age=21, sex='null'}, User{username='aaa', age=25, sex='null'}, User{username='zhangsan', age=21, sex='null'}, User{username='zhangsan', age=23, sex='null'}]
select(…)方法:用来设置查询的字段列,可以设置多个,用逗号分割
@Test
void testConditionSearch8(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("username","age");
List<User> users = userMapper.selectList(queryWrapper);
System.out.println(users);//[User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='aaa', age=25, sex='男'}, User{username='zhangsan', age=21, sex='男'}, User{username='zhangsan', age=23, sex='男'}]
}
聚合查询函数一般常有的有:count(记录总条数),max(最大值),min(最小值),avg(平均数),sum(求和)
//聚合函数
@Test
void testConditionSearch9() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//生成的sql语句:SELECT count(*) as count FROM user
queryWrapper.select("count(*) as count");
//生成的sql语句:SELECT max(age) as max_age FROM user
queryWrapper.select("max(age) as max_age");
//生成的sql语句:SELECT min(age) as min_age FROM user
queryWrapper.select("min(age) as min_age");
//生成的sql语句:SELECT avg(age) as avg_age FROM user
queryWrapper.select("avg(age) as avg_age");
//生成的sql语句:SELECT sum(age) as sum_age FROM user
queryWrapper.select("sum(age) as sum_age");
//使用selectMaps方法使用键值对的方式看到结果,例如:[{sum_age=111}]
List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
System.out.println(users);
}
@Test
void testConditionSearch10(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//下面两行生成的sql语句:SELECT max(age) as max_age,age FROM user GROUP BY age
queryWrapper.select("max(age) as max_age,age");
queryWrapper.groupBy("age");
List<User> users = userMapper.selectList(queryWrapper);
System.out.println(users);//[User{id=0, username='null', age=21, sex='null'}, User{id=0, username='null', age=23, sex='null'}, User{id=0, username='null', age=25, sex='null'}]
}
**注意:**聚合查询和分组查询无法使用lambda表达式完成
gt():大于(>)
ge():大于等于(>=)
lt():小于(<)
lte():小于等于(<=)
between():between ? and ?
eq():等值查询
like():前后加百分号,如 %J%
likeLeft():前面加百分号,如 %J
likeRight():后面加百分号,如 J%
orderBy排序
orderByAsc/Desc(单个column):按照指定字段进行升序/降序
orderByAsc/Desc(多个column):按照多个字段进行升序/降序
orderByAsc/Desc
以上只是一些常用方法,其它具体情况可以参照:条件构造器 | MyBatis-Plus (baomidou.com)
从数据库表中取出数据后,需要封装到指定模型中去,当数据库表中的字段名和实体中的属性名一致时,可以直接成功进行操作
public class User {
private int id;
private String username;
private Integer age;
private String sex;
}
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` char(2) DEFAULT NULL,
PRIMARY KEY (`id`)
)
在实际业务中,可能会出现数据库表中的字段名和实体类中的属性名不一致的情况,为了解决这种情况,Mybatis-plus提供来一个@TableField
注解来解决这个问题。
名称 | @TableField |
---|---|
类型 | 属性注解 |
位置 | 实体类属性定义上方 |
作用 | 设置当前属性对应的数据库表中的字段关系 |
相关属性 | value(默认):设置数据库表字段名称 exist:设置属性在数据库表字段中是否存在,默认为true,此属性不能与value合并使用 select:设置属性是否参与查询,此属性与select()映射配置不冲突 |
public class User {
private int id;
@TableField(value = "username",exist = true,select = true)
private String uname;
private Integer age;
private String sex;
}
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` char(2) DEFAULT NULL,
PRIMARY KEY (`id`)
)
当实体类中出现一个数据库表中未定义的字段,查询就会报错,解决方案还是使用@TableField
这个注解,这个注解中有一个exist
属性,表示属性在数据库中是否存在,如果值为true则表示存在,为false则不存在,值为false时,在进行查询时不会去查询此字段的值。
public class User {
private int id;
@TableField(value = "username",exist = true,select = true)
private String uname;
private Integer age;
private String sex;
@TableField(exist = false)
private String status;
}
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` char(2) DEFAULT NULL,
PRIMARY KEY (`id`)
)
实际业务中,有一些敏感数据可能不想让其它人看到,所以对数据的查看需要进行一些设置,使用@TableField
注解可以进行设置哪些属性不被查询,@TableField
有一个属性select
,用于设置默认是否查询该字段的值,值为true则查询,值为false则不查询。
public class User {
private int id;
@TableField(value = "username",exist = true,select = true)
private String uname;
@TableField(select = false)
private Integer age;
private String sex;
}
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` char(2) DEFAULT NULL,
PRIMARY KEY (`id`)
)
在实际业务中,可能会出现数据库表名和实体类名不一致的情况,为了解决这种情况,Mybatis-plus提供来一个@TableName
注解来解决这个问题。
名称 | @TableName |
---|---|
类型 | 类注解 |
位置 | 实体类定义上方 |
作用 | 设置当前类对应于数据库表关系 |
相关属性 | value(默认):设置数据库表名称 |
@TableName("user")
public class User3 {
private int id;
private String username;
private Integer age;
private String sex;
}
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` char(2) DEFAULT NULL,
PRIMARY KEY (`id`)
)