笔记mybatisplus

devtools/2024/10/18 5:44:46/

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_UUIDUUID生成的字符串
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;
}

综合案例

  1. 添加页面
  2. 运行程序
  3. 访问页面

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的插件完成代码生成

  1. 安装插件
  2. 配置数据源
  3. 代码生成

安装插件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

配置数据源

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)]


http://www.ppmy.cn/devtools/98777.html

相关文章

大白话讲微服务的灾难性雪崩效应

讲在前面&#xff0c;为什么微服务需要有熔断等策略呢&#xff1f;今天我们用大白话来讲讲微服务的灾难性雪崩效应&#xff0c;熔断策略就是解决雪崩效应的有效解决方案。 什么是灾难性雪崩效应&#xff1f; 假设我们有两个访问量比较大的服务A和B&#xff0c;这两个服务分别依…

婚恋交友系统该如何制作成品系统?

制作婚恋交友系统的成品系统是一个综合性的过程&#xff0c;涉及多个关键步骤和技术要点。以下是一个详细的制作流程&#xff1a; 1. 需求分析 市场调研&#xff1a;首先需要对婚恋交友市场进行深入调研&#xff0c;了解目标用户群体的需求、喜好、习惯以及市场痛点。用户画像…

Qt实现圆型控件的三种方法之子类化控件并重写paintEvent

前言 最近在研究绘制各种形状的控件&#xff0c;这里专门挑出圆形的控件进行记录&#xff0c;其它形状的也大差不差&#xff0c;会了圆形的之后其它的也类似。 正文 这里我挑出Label来进行举例。 子类化 QLabel 并重写 paintEvent 如果需要更复杂的自定义绘制&#xff0c;…

0成本学习Liunx系统【只需要一台笔记本电脑,无需购买云服务器】

【准备工作&#xff0c;需要软件】&#xff1a; 1&#xff1a;MobaXterm 【服务器连接工具&#xff08;免费开源&#xff09;】 2&#xff1a;CentOS-7-x86_64-DVD-2009.iso 【CentOS-7 镜像】 3&#xff1a;VirtualBox-7.0.20-163906-Win.exe 【虚拟机壳子】 4&…

多个echarts使用3D导致页面卡顿的解决办法

如果使用echarts自带的clear()和dispose()方法没有明显效果的话&#xff0c;可以使用页面的loseContext()对echarts进行手动清除&#xff0c;最好放到router.js里的路由守卫(router.beforeEach)里执行,也可以在APP.vue下监听路由的变化进行清除&#xff0c;自行决定即可&#x…

加载的案例

<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8" /> <meta name"viewport" content"widthdevice-width, initial-scale1.0" /> <title>下滑加载历史</title> …

SQL每日一练-0816

今日SQL题&#xff1a;计算每个项目的年度收入增长率 难度系数&#xff1a;&#x1f31f;☆☆☆☆☆☆☆☆☆ 1、题目要求 计算每个项目每年的收入总额&#xff0c;并计算项目收入环比增长率。找出每年收入增长率最高的项目。输出结果显示年份、项目ID、项目名称、项…

海外媒体软文发稿【越南通讯社vnanet】官方媒体发布新闻稿

海外媒体软文发稿【越南通讯社vnanet】官方媒体发布新闻稿 越南通讯社(越南语&#xff1a;Thng tấn x Việt Nam&#xff1b;英语&#xff1a;Vietnam News Agency&#xff0c;简称VNA)&#xff0c;简称“越通社”是越南国家通讯社&#xff0c;始建于1945年9月2日。越通社是越…