MP入门
Mybatis-Plus(简称MP)是一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发、提高效率而生。
Mybatis-Plus已经封装好了大量增删改查的方法,程序员只需要继承BaseMapper就可以使用这些方法了,无需自己再开发。
官网地址:https://baomidou.com/
案例实现
向数据库保存一个User对象
创建数据表
create table tb_user (id bigint(20) primary key auto_increment,username varchar(30) unique not null,name varchar(30) not null,password varchar(32) not null,age int(3) not null ,tel varchar(32) not null,create_time datetime,update_time datetime
);
insert into tb_user values(1,'heima1','tom','123456',12,'12345678911',now(),now());
insert into tb_user values(2,'heima2','jack','123456',8,'12345678912',now(),now());
insert into tb_user values(3,'heima3','jerry','123456',15,'12345678910',now(),now());
insert into tb_user values(4,'heima4','tom','123456',9,'12345678910',now(),now());
insert into tb_user values(5,'heima5','snake','123456',28,'12345678910',now(),now());
insert into tb_user values(6,'heima6','张益达','123456',22,'12345678910',now(),now());
insert into tb_user values(7,'heima7','张大炮','123456',16,'12345678910',now(),now());
创建工程
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.3</version></parent><dependencies><!--mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.3</version></dependency><!--mybatis plus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency><!--lombok简化对象书写--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--hutool工具包--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.20</version></dependency><!--整合测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!--web环境依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>
创建实体类
package com.itheima.domain;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Long id;private String username;private String name;private String password;private Integer age;private String tel;private LocalDateTime createTime;private LocalDateTime updateTime;
}
创建接口
自定义的Mapper接口需要实现BaseMapper<实体类>,然后就可以继承到BaseMapper中定义的方法了
package com.itheima.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.domain.User;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface UserMapper extends BaseMapper<User> {//声明方法+注解实现sql}
添加配置文件
在resources中添加配置文件application.yml,然后在里面加入下面配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mpusername: rootpassword: root# druid 阿里 HkariCp(springBoot)type: com.alibaba.druid.pool.DruidDataSourcemybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志打印map-underscore-to-camel-case: true # 驼峰映射
创建启动类
package com.itheima;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MpApplication {public static void main(String[] args) {SpringApplication.run(MpApplication.class,args);}
}
测试
package com.itheima.test;import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testInsert() {//1. 封装user对象User user = User.builder().username("baima1").name("tom").password("123456").age(18).tel("13700137001").build();//2. 调用mapper方法userMapper.insert(user);}
}
案例细节
@TableName
标注在实体类上,用于声明实体类对应的表,如果表名和类名一致可以省略
//标注在实体类上,用于声明实体类对应的表,如果表名和类名一致可以省略
@TableName("tb_user")
public class User {....
}
如果大部分表都是以固定前缀开头,可以全局配置表前缀,但优先级比注解配置低
mybatis-plus:global-config:db-config:table-prefix: tb_ #表前缀
@TableId
标注在主键字段上,用于声明主键生成策略
//主键生成策略//AUTO : 数据库的自增//INPUT: 让用户自己输入主键//ASSIGN_ID: 雪花算法生成的一个纯数字//ASSIGN_UUID: UUID生成一个不重复字符串//ASSIGN_NONE: INPUT+ASSIGN_ID@TableId(type = IdType.AUTO)private Long id;
值 | 描述 |
---|---|
AUTO | 数据库主键自增 |
INPUT | 手动设置主键值 |
ASSIGN_ID | 由雪花算法生成的纯数字 |
ASSIGN_UUID | UUID生成的字符串 |
NONE | 默认值 相当于INPUT+ASSIGN_ID |
如果大部分表主键都是自增,可以进行全局设置,但优先级比注解配置低
mybatis-plus:global-config:db-config:id-type: auto #主键策略table-prefix: tbl_ #表前缀
Mapper接口
BaseMapper:通用 CRUD 接口,内部声明了大量的单表操作方法,泛型
T
为任意实体对象
@Mapper
public interface ProductMapper extends BaseMapper<Product> {}
基本使用
MybatisPlus提供了单表的增删改查方法,常用的如下
// 插入一条记录 int insert(T entity);// 主键查询 T selectById(Serializable id); // 主键批量查询 List<T> selectBatchIds(Collection idList); // 根据ID修改不为空的字段 int updateById(T entity);// 根据ID删除 int deleteById(Serializable id);// 根据ID集合批量删除 int deleteBatchIds(Collection idList);
package com.itheima.test;import cn.hutool.core.collection.ListUtil;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.ArrayList;
import java.util.List;@SpringBootTest
public class UserMapperTest {@Autowiredprivate UserMapper userMapper;//插入一条记录//int insert(T entity);@Testpublic void testInsert() {//1. 封装user对象User user = User.builder().username("baima1").name("tom").password("123456").age(18).tel("13700137001").build();//2. 调用mapper方法userMapper.insert(user);}//主键查询//T selectById(Serializable id);@Testpublic void testSelectById() {User user = userMapper.selectById(1L);System.out.println(user);}//主键批量查询//List<T> selectBatchIds(Collection idList);@Testpublic void testSelectBatchIds() {//1. 构建id集合List<Long> idList = ListUtil.of(1L, 2L, 3L);//2. 执行查询List<User> userList = userMapper.selectBatchIds(idList);System.out.println(userList);}//根据ID修改不为空的字段//int updateById(T entity);@Testpublic void testUpdateById() {//1. 封装user对象User user = User.builder().username("baima2").name("tom2").tel("13700137002").id(2L)//不要忘记设置id.build();userMapper.updateById(user);}//根据ID删除//int deleteById(Serializable id);@Testpublic void testDeleteById() {userMapper.deleteById(7L);}//根据ID集合批量删除//int deleteBatchIds(Collection idList);@Testpublic void testDeleteBatchIds() {List<Long> idList = ListUtil.of(1L, 2L, 3L);userMapper.deleteBatchIds(idList);}
}
条件查询
MybatisPlus提供了Wrapper对象来封装各种条件,比如条件、分页、排序、分组、过滤等等
// 条件查询,当查询结果最多为一条记录时使用 手机号 身份证号 用户名 唯一约束 T selectOne(Wrapper<T> queryWrapper);// 条件查询,当查询结果可能为多条记录时使用 List<T> selectList(Wrapper<T> queryWrapper);
书写格式
MybatisPlus支持使用多种格式组装条件,我们推荐使用Lambda格式
package com.itheima.test;import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
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
public class UserMapperTest2 {@Autowiredprivate UserMapper userMapper;//根据name=白马1和age>18查询(支持动态sql)@Testpublic void testSelectList1() {//0. 模仿前端传入参数String name = null;Integer age = 18;//1. 构建查询条件QueryWrapper<User> wrapper = new QueryWrapper<>();if (StrUtil.isNotEmpty(name)) {wrapper.eq("name", name); //where name = '白马'}if (age != null) {wrapper.gt("age", age);//and age > 18}//2. 查询List<User> userList = userMapper.selectList(wrapper);userList.forEach(System.out::println);}//Lambda 根据name=白马1和age>18查询(支持动态sql)@Testpublic void testSelectList2() {//0. 模仿前端传入参数String name = "白马";Integer age = 18;//1. 构建查询条件LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();//参数1位置是一个boolean值,只有这个值为true,当前条件才会生效wrapper.eq(StrUtil.isNotEmpty(name), User::getName, name);//where name = '白马'wrapper.gt(age != null, User::getAge, age);//and age > 18//2. 查询List<User> userList = userMapper.selectList(wrapper);userList.forEach(System.out::println);}//Lambda链式 根据name=白马1和age>18查询(支持动态sql)@Testpublic void testSelectList3() {//0. 模仿前端传入参数String name = "白马";Integer age = 18;//1. 构建查询条件LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();//参数1位置是一个boolean值,只有这个值为true,当前条件才会生效wrapper.eq(StrUtil.isNotEmpty(name), User::getName, name)//where name = '白马'.gt(age != null, User::getAge, age);//and age > 18//2. 查询List<User> userList = userMapper.selectList(wrapper);userList.forEach(System.out::println);}
}
查询条件
查询方法 | 说明 | 例子 |
---|---|---|
eq、ne、gt、ge、lt、le、isNull、isNotNull | 比较运算 | eq(“name”, “老王”)---> name = ‘老王’ |
like、notLike、likeLeft、likeRight | 模糊查询 | likeRight(“name”, “王”)---> name like ‘王%’ |
in、notIn、between、notBetween | 范围运算 | in(“age”,{1,2,3})---> age in (1,2,3) |
or、and | 拼接 | eq(“id”,1).or().eq(“name”,“老王”)---> id = 1 or name = ‘老王’ |
//select * from tb_user where//id >= 1//and username = 'baima'//and name like '%马'//and age between 10 and 30//or tel in ('1370013001','1370013002')@Testpublic void testSelectList4() {//0. 模仿前端传入参数String name = "白马";Integer age = 18;//1. 构建查询条件LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.ge(User::getId,1).eq(User::getUsername,"baima").likeLeft(User::getName,'马').between(User::getAge,10,30).or().in(User::getTel,List.of("1370013001","1370013002"));//2. 查询List<User> userList = userMapper.selectList(wrapper);userList.forEach(System.out::println);}
其他条件
除了设置查询条件外,MP还支持:投影、排序、分组、过滤等功能
查询方法 | 说明 | 例子 |
---|---|---|
select | 投影 | select(“name”,“password”)---> select name,password from 表 |
orderByAsc、orderByDesc | 排序 | orderByDesc(“id”, “name”)---> order by id DESC,name DESC |
groupBy | 分组 | groupBy(“id”, “name”)---> group by id,name |
having | 过滤 | having(“sum(age) > 10”)---> having sum(age) > 10 |
package com.itheima.test;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import com.itheima.vo.Re;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;
import java.util.Map;@SpringBootTest
public class UserMapperTest2 {@Autowiredprivate UserMapper userMapper;//投影和排序//select name,age from tb_user where id > 1 order by age desc@Testpublic void testSelectList1() {//1. 构建查询条件LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.gt(User::getId,1);//id > 1wrapper.select(User::getName,User::getAge);//select name,agewrapper.orderByDesc(User::getAge);//order by age descwrapper.orderByAsc(User::getId);//order by id asc//2. 查询List<User> userList = userMapper.selectList(wrapper);userList.forEach(System.out::println);}//分组和过滤//select age,count(*) from tb_user group by age having count(*) >= 2@Testpublic void testSelectList2() {//1. 构建查询条件(LambdaQueryWrapper不支持分组和过滤)QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.select("age","count(*)");//select age,count(*)wrapper.groupBy("age");//group by agewrapper.having("count(*) >= 2");//having count(*) >= 2//2. 查询List<Map<String, Object>> list = userMapper.selectMaps(wrapper);list.forEach(System.out::println);}//分组和过滤//select age,count(*) from tb_user group by age having count(*) >= 2@Testpublic void testSelectList3() {List<Map<String, Object>> list = userMapper.count1();list.forEach(System.out::println);}@Testpublic void testSelectList4() {List<Re> list = userMapper.count2();list.forEach(System.out::println);}
}
UserMapper
package com.itheima.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.domain.User;
import com.itheima.vo.Re;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;
import java.util.Map;//自定义的Mapper 要求继承BaseMapper<实体类类型>
@Mapper
public interface UserMapper extends BaseMapper<User> {//自定义@Select("select age,count(*) from tb_user group by age having count(*) >= 2")List<Map<String, Object>> count1();@Select("select age,count(*) as num from tb_user group by age having num >= 2")List<Re> count2();
}
Re
package com.itheima.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@NoArgsConstructor
@AllArgsConstructor
@Data
public class Re {private String age;private Integer num;
}
分页查询
MybatisPlus内置了专门用于分页的插件,使用起来非常简单,它是基于拦截器原理实现分页的
① 配置拦截器
package com.itheima.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 MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){//1 创建MybatisPlusInterceptor拦截器对象MybatisPlusInterceptor mpInterceptor=new MybatisPlusInterceptor();//2 添加分页拦截器mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mpInterceptor;}
}
② 分页代码实现
//分页查询//select * from tb_user where id > 1 limit 5,7@Testpublic void testPage() {//1. 设置分页条件 当前页面 每页条数Page<User> page = new Page<>(2, 3);//2. 设置业务条件LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.eq(User::getAge, 18);//3. 调用分页方法page = userMapper.selectPage(page, wrapper);//4. 获取分页结果System.out.println("总条数:" + page.getTotal());System.out.println("总页数:" + page.getPages());System.out.println("当前页数据集合:" + page.getRecords());}
条件修改
// 参数1: 封装要修改的字段 参数2: 封装更新条件 int update(T entity,Wrapper<T> updateWrapper);
package com.itheima.test;import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class UserMapperTest4 {@Autowiredprivate UserMapper userMapper;//条件更新//update tb_user set age = 10,password = '123123' where name = 'tom'@Testpublic void testUpdate() {//1. 设置更新条件LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();wrapper.eq(User::getName, "tom");//2. 设置更新字段User user = User.builder().age(10).password("123123").build();//3. 执行更新userMapper.update(user, wrapper);}
}
条件删除
// 条件删除 int delete(Wrapper<T> wrapper);
//条件删除//delete from tb_user where name = 'tom';@Testpublic void testDelete() {//1. 设置删除条件LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();wrapper.eq(User::getName, "tom");//2. 执行删除userMapper.delete(wrapper);}
实用功能
逻辑删除
逻辑删除指的是:当执行删除操作时,并不是将对应记录真正从数据库删掉,而是使用一个标识列,将要删除的数据标识为删除状态
MP使用@TableLogic就可以轻松实现这个功能
①:在user表中添加逻辑删除标记字段,并设置默认值为0
②:实体类中添加对应字段,设定为当前字段为逻辑删除标记字段
//逻辑删除字段:value用于指定未删除状态的值, delval用于指定删除状态的值@TableLogic(value = "0", delval = "1")private Integer deleted;
③ 删除其中一个用户观察效果
@TableLogic 只是单个表设置逻辑删除字段,如果多张表都需要配置逻辑删除,则可以做全局配置
mybatis-plus:global-config:db-config:logic-delete-field: deleted # 全局逻辑删除的实体字段名logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
自动填充
对于数据表中的一些公共字段,我们可以使用mybatisplus的自动填充功能来统一设置值
@TableField注解的fill属性可以完成这个功能 [1. 什么时候填充 2. 填充什么值]
① 在实体类的字段上添加注解
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
值 | 描述 |
---|---|
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
② 在配置类中设置要填充的值
package com.itheima.config;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {//新增时执行此方法@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill ....");this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}//修改时执行此方法@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ....");this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); }
}
③ 测试
//自动填充@Testpublic void testFill(){//1. 封装user对象User user = User.builder().username("baima10").name("tom10").password("123456").age(18).tel("13700137001").build();//2. 调用mapper方法userMapper.insert(user);}
多余属性
多余属性指的是:实体类中存在,但是在数据表没有对应字段的属性
此时需要使用@TableField(exist = false)标识此属性
package com.itheima.domain;import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDateTime;@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
//标注在实体类上,用于声明实体类对应的表,如果表名和类名一致可以省略
//@TableName("tb_user")
public class User {//type: 声明主键生成策略@TableId(type = IdType.AUTO)private Long id;private String username;private String name;private String password;@TableField(exist = false)//表示当前属性仅在实体类中存在,在数据表中没有对应的字段private String password2;private Integer age;private String tel;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;//逻辑删除字段:value用于指定未删除状态的值, delval用于指定删除状态的值//@TableLogic(value = "1", delval = "0")private Integer deleted;
}
综合案例
- 添加页面
- 运行程序
- 访问页面
UserController
package com.itheima.controller;import com.itheima.domain.User;
import com.itheima.service.UserService;
import com.itheima.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/user")public Result findList(){List<User> userList = userService.findList();return Result.success(userList);}@PostMapping("/user")public Result save(@RequestBody User user){userService.save(user);return Result.success();}@DeleteMapping("/user/{id}")public Result deleteById(@PathVariable("id") Long id){userService.deleteById(id);return Result.success();}@GetMapping("/user/{id}")public Result findById(@PathVariable("id") Long id){User user = userService.findById(id);return Result.success(user);}@PutMapping("/user")public Result update(@RequestBody User user){userService.update(user);return Result.success();}
}
UserService
package com.itheima.service;import com.itheima.domain.User;import java.util.List;public interface UserService {List<User> findList();void save(User user);void deleteById(Long id);User findById(Long id);void update(User user);
}
UserServiceImpl
package com.itheima.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import com.itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic List<User> findList() {return userMapper.selectList(new LambdaQueryWrapper<>());}@Overridepublic void save(User user) {userMapper.insert(user);}@Overridepublic void deleteById(Long id) {userMapper.deleteById(id);}@Overridepublic User findById(Long id) {return userMapper.selectById(id);}@Overridepublic void update(User user) {userMapper.updateById(user);}
}
ID精度损失问题
后端返回一个Long的id时候,前端接收到的数据精度有损失
pom.xml
<dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.13.0</version></dependency>
WebMvcConfig
package com.itheima.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.math.BigInteger;
import java.util.List;import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;@Configuration
public class WebMvcConfig implements WebMvcConfigurer {//扩展mvc框架的消息转换器public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {//创建消息转换器对象MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();//设置对象转换器,底层使用Jackson将Java对象转为jsonmessageConverter.setObjectMapper(new JacksonObjectMapper());//将上面的消息转换器对象追加到mvc框架的转换器集合中converters.add(0, messageConverter);}/*** 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]*/public class JacksonObjectMapper extends ObjectMapper {public JacksonObjectMapper() {super();//对应JDK8+ 时间类型处理需要添加的模块this.registerModule(new JavaTimeModule());//收到未知属性时不报异常this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);//反序列化时,属性不存在的兼容处理this.getDeserializationConfig().withoutFeatures(FAIL_ON_UNKNOWN_PROPERTIES);//自定义转换规则SimpleModule simpleModule = new SimpleModule().addSerializer(BigInteger.class, ToStringSerializer.instance)//将BigInteger转换为String.addSerializer(Long.class, ToStringSerializer.instance);//将Long转换成Stringthis.registerModule(simpleModule);}}
}
Service接口
介绍
为了简化service代码编写,mybatisPlus也提供了的基础接口和实现类
我们只需要让我们自己的service去继承它提供的service,就可以使用里面的方法
进一步封装 CRUD 采用 get 查询单行
remove 删除
list 查询集合
page 分页
前缀命名方式区分 Mapper
层避免混淆
分类 | 方法 | 描述 |
---|---|---|
新增 | boolean save(T entity) | 新增,entity 实体对象 |
boolean saveOrUpdate(T entity) | id存在则更新记录,否插入一条记录 | |
boolean saveBatch(Collection entityList) | 插入(批量),默认一次可以保存1000条数据 | |
修改 | boolean updateById(T entity) | 根据 ID 修改 |
boolean update(T entity,Wrapper updateWrapper) | 根据 条件 修改 | |
查询 | T getById(Serializable id) | 根据 ID 查询 |
List listByIds(Collection idList) | 查询(根据ID 批量查询) | |
List list() | 查询所有 | |
List list(Wrapper queryWrapper) | 条件查询 | |
删除 | boolean removeById(Serializable id) | 根据 ID 删除 |
boolean removeByIds(Collection idList) | 删除(根据ID 批量删除) | |
boolean remove(Wrapper queryWrapper) | 根据条件删除 |
修改Service
使用Service 接口使用
- 接口继承 IService
- 实现类继承 ServiceImpl<M,T>
UserService
package com.itheima.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.domain.User;//自定义service接口
public interface UserService extends IService<User> {}
UserServiceImpl
package com.itheima.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.domain.User;
import com.itheima.mapper.UserMapper;
import com.itheima.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}
修改controller
package com.itheima.controller;import com.itheima.domain.User;
import com.itheima.service.UserService;
import com.itheima.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/user")public Result findList(){List<User> userList = userService.list();return Result.success(userList);}@PostMapping("/user")public Result save(@RequestBody User user){userService.saveOrUpdate(user);return Result.success();}@DeleteMapping("/user/{id}")public Result deleteById(@PathVariable("id") Long id){userService.removeById(id);return Result.success();}@GetMapping("/user/{id}")public Result findById(@PathVariable("id") Long id){User user = userService.getById(id);return Result.success(user);}@PutMapping("/user")public Result update(@RequestBody User user){userService.saveOrUpdate(user);return Result.success();}
}
代码生成器
mybatis-plus官方提供了代码生成器,可以根据数据库表,逆向生成 Controller Service Mapper代码
这里使用 IDEA的插件完成代码生成
- 安装插件
- 配置数据源
- 代码生成
安装插件
配置数据源
jdbc:mysql://localhost:3306/mp_demo?useUnicode=true&IntegerEncoding=utf8&useSSL=false&servertimeZone=Asia/Shanghai
代码生成
多表查询
表间关系
添加新表
CREATE TABLE `tb_account` (`aid` INT(11) PRIMARY KEY AUTO_INCREMENT,`accountName` VARCHAR(100) DEFAULT NULL,`balance` FLOAT(10,2) DEFAULT NULL,`uid` INT(11) DEFAULT NULL
);
INSERT INTO `tb_account` VALUES
(1,'B01',100.00,1),
(2,'B02',200.00,1),
(3,'B03',300.00,1),
(4,'B04',400.00,2);
package com.itheima.domain;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import lombok.experimental.Accessors;import java.io.Serializable;
import java.time.LocalDateTime;/*** <p>* 账户* </p>** @author gxm* @since 2024-08-11*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_account")
@Builder
public class Account implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "aid", type = IdType.AUTO)private Long aid;@TableField("accountName")private String accountName;@TableField("balance")private Float balance;@TableField("uid")private Integer uid;
}
查询所有账户, 并且带出账户的用户信息
建立关系
接口
映射
<?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.itheima.mapper.AccountMapper"><!--自定义结果映射--><resultMap id="BaseResultMap" type="com.itheima.domain.Account"><result column="aid" property="aid"></result><result column="accountName" property="accountName"></result><result column="balance" property="balance"></result><result column="uid" property="uid"></result><association property="user" javaType="com.itheima.domain.User"><result column="id" property="id"></result><result column="username" property="username"></result><result column="name" property="name"></result><result column="password" property="password"></result><result column="age" property="age"></result><result column="tel" property="tel"></result><result column="create_time" property="createTime"></result><result column="update_time" property="updateTime"></result><result column="deleted" property="deleted"></result></association></resultMap><!-- 通用查询映射结果 --><select id="findAllWithUser" resultMap="BaseResultMap">select * from tb_account a left join tb_user u on a.uid = u.id</select>
</mapper>
测试
查询所有用户, 并且带出用户的账户信息
建立关系
接口
映射
<?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.itheima.mapper.UserMapper"><!-- 通用查询映射结果 --><resultMap id="BaseResultMap" type="com.itheima.domain.User"><id column="id" property="id" /><result column="username" property="username" /><result column="name" property="name" /><result column="password" property="password" /><result column="age" property="age" /><result column="tel" property="tel" /><result column="create_time" property="createTime" /><result column="update_time" property="updateTime" /><result column="deleted" property="deleted" /><collection property="accountList" ofType="com.itheima.domain.Account"><result column="aid" property="aid" /><result column="accountName" property="accountName" /><result column="balance" property="balance" /><result column="uid" property="uid" /></collection></resultMap><select id="findAllWithAccount" resultMap="BaseResultMap">select * from tb_user u left join tb_account a on a.uid = u.id</select></mapper>
测试
[外链图片转存中…(img-jtmFAVvw-1724395263711)]
接口
[外链图片转存中…(img-ryL3e27c-1724395263712)]
映射
<?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.itheima.mapper.UserMapper"><!-- 通用查询映射结果 --><resultMap id="BaseResultMap" type="com.itheima.domain.User"><id column="id" property="id" /><result column="username" property="username" /><result column="name" property="name" /><result column="password" property="password" /><result column="age" property="age" /><result column="tel" property="tel" /><result column="create_time" property="createTime" /><result column="update_time" property="updateTime" /><result column="deleted" property="deleted" /><collection property="accountList" ofType="com.itheima.domain.Account"><result column="aid" property="aid" /><result column="accountName" property="accountName" /><result column="balance" property="balance" /><result column="uid" property="uid" /></collection></resultMap><select id="findAllWithAccount" resultMap="BaseResultMap">select * from tb_user u left join tb_account a on a.uid = u.id</select></mapper>
测试
[外链图片转存中…(img-MPWRWmeR-1724395263712)]