笔记mybatisplus

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.mzph.cn/news/877756.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux阿里云服务器,利用docker安装EMQX

第一步&#xff0c;给云服务器docker进行加速 阿里云搜索“镜像加速器”&#xff0c;找到下面这个菜单&#xff0c;点进去 然后找到镜像工具下的镜像加速器 把这个加速器地址复制 然后在自己的云服务器中&#xff0c;找到docker的文件夹 点击json配置文件 把地址修改为刚刚…

如何将LaTeX数学公式嵌入到PowerPoint中

如何将LaTeX数学公式嵌入到PowerPoint中 简介 在学术演示或技术报告中&#xff0c;清晰且专业地展示数学公式是至关重要的。PowerPoint虽然提供了一些基本的公式编辑功能&#xff0c;但如果你需要更复杂或格式严格的公式&#xff0c;使用LaTeX生成公式并嵌入到PPT中是一个极佳…

Python酷库之旅-第三方库Pandas(092)

目录 一、用法精讲 391、pandas.Series.hist方法 391-1、语法 391-2、参数 391-3、功能 391-4、返回值 391-5、说明 391-6、用法 391-6-1、数据准备 391-6-2、代码示例 391-6-3、结果输出 392、pandas.Series.to_pickle方法 392-1、语法 392-2、参数 392-3、功能…

KT来袭,打造沉浸式体验的聚合性web3应用平台

随着步入 2024&#xff0c;漫长的区块链熊市即将接近尾声。纵观产业发展&#xff0c;逆流而上往往会是彰显品牌市场影响力和技术实力的最佳证明。在这次周期中&#xff0c;一个名为KT的web3.0聚合平台吸引了市场关注&#xff0c;无论在市场层面还是技术层面&#xff0c;都广泛赢…

听劝❗用AI做职场思维导图仅仅需要几秒钟啊

本文由 ChatMoney团队出品 嘿&#xff0c;各位职场朋友们 是不是常常对着密密麻麻的笔记感到焦虑呢&#xff1f; 想整理却无从下手&#xff1f; 别怕&#xff0c;ChatmoneyAI知识库来拯救你的整理困难症啦&#xff01; 咱们都知道&#xff0c;思维导图是职场中必备的神器 …

zoom 会议机器人web例子

一、需要创建zoom app&#xff0c;创建及配置参考&#xff1a;Zoom会议机器人转写例子-CSDN博客 这里直接使用zoom-recall的配置。 二、需要生成签名&#xff0c;参数为&#xff1a;zoom-recall中的Client ID和Client Secret 1、git clone https://github.com/zoom/meetings…

【PHP入门教程】PHPStudy环境搭建+composer创建项目

文章目录 PHP 的历史PHP 的用途PHP 的特点和优势PHP 环境搭建环境准备安装window 安装CentOS / Ubuntu / Debian 安装 第一个Hello World使用Apache服务运行命令行运行代码 Composer安装 Composer&#xff1a;安装途中报错解决&#xff1a;初始化项目创建文件最终文件目录Compo…

微服务:配置管理和配置热更新

参考&#xff1a;黑马程序员之微服务 &#x1f4a5; 该系列属于【SpringBoot基础】专栏&#xff0c;如您需查看其他SpringBoot相关文章&#xff0c;请您点击左边的连接 目录 一、引言 二、配置共享 1. 添加共享配置到nacos &#xff08;1&#xff09;jdbc的共享配置 shared…

设计模式之Decorator装饰者、Facade外观、Adapter适配器(Java)

装饰者模式 设计模式的基本原则&#xff0c;对内关闭修改。 Decorator Pattern&#xff0c;装饰者模式&#xff0c;也叫包装器模式(Wrapper Pattern)&#xff1a;将一个对象包装起来&#xff0c;增加新的行为和责任。一定是从外部传入&#xff0c;并且可以没有顺序&#xff0…

望繁信科技入选2024年第3批上海市高新技术成果转化项目名单

近日&#xff0c;上海望繁信科技有限公司&#xff08;以下简称“望繁信科技”&#xff09;凭借其自主研发的“数字北极星流程挖掘分析软件”项目&#xff0c;成功入选2024年第3批上海市高新技术成果转化项目名单。这一殊荣根据《上海市高新技术成果转化项目认定办法》&#xff…

Keil Error-Flash Download failed Cortex-M4 擦除芯片还不好使的方案!!!

点击魔术棒-Debug-Settings后看到SWDIO可以正常识别&#xff0c;但是点击Reset下拉只有三个选项。 此时点击Pack&#xff0c;将Enable勾去掉。 回到Reset&#xff0c;此时多了Autodetet选项&#xff0c;选择这个选项后&#xff0c;即可正常烧录。

CLI举例:通过ISAKMP方式建立GRE over IPsec隧道

配置安全策略&#xff0c;允许私网指定网段进行报文交互&#xff0c;放行IKE协商报文。配置静态路由&#xff0c;保证两端路由可达。配置GRE Tunnel接口以及Tunnel口的转发路由。配置基于ACL的IPsec策略。GRE over IPsec中IPsec需要保护的数据流以GRE的起点为源、终点为目的。 …

初始C++(类与对象)

感谢大佬的光临各位&#xff0c;希望和大家一起进步&#xff0c;望得到你的三连&#xff0c;互三支持&#xff0c;一起进步 个人主页&#xff1a;LaNzikinh-CSDN博客 文章目录 前言一.引用二.内联函数三.类和对象总结 前言 之前讲c的命令空间和第一个程序的运行&#xff0c;继…

Aixos食用指南,超全面详细讲解!

前言&#xff1a;axios是目前最流行的ajax封装库之一&#xff0c;用于很方便地实现ajax请求的发送。特意花费了两个小时为大家准备了一份全面详细的Aixos食用指南&#xff0c;需要的小伙伴点个关注 哦~&#x1f495; &#x1f308;&#x1f308;文章目录 Axios 简介 Axios 特…

vue实现卡片遮罩层交互式功能

前言 在前端开发中&#xff0c;卡片遮罩层是一种常见的交互设计元素&#xff0c;用于强调某个区域或内容&#xff0c;并提供用户操作的入口。本文将带大家在 vue 中结合实际案例实现此功能。 实现效果 完整代码 html <template><!-- 主容器 --><div class&quo…

ctfshow WEB刷题

web1 直接右键打开&#xff0c;在源代码里 web2 ctrlu查看源码 web3 打开bp抓包发送直接就得到了 web4 用dirsearch扫描发现txt文件 访问 接着访问得到flag web5 用dirbuster扫描看看有没有phps源码泄露&#xff0c;发现存在 访问下载文件打开就是flag web6 用dirsearch扫…

ES6笔记总结(Xmind格式):第三天

Xmind鸟瞰图&#xff1a; 简单文字总结&#xff1a; ES6知识总结&#xff1a; Promise的使用: 1.使用 new Promise() 构造函数来创建一个 promise 对象 2.接受两个函数作为参数&#xff1a;resolve 和 reject ①resolve 函数在异步操作成功完成时调用&#xf…

python构建一个web程序

from flask import Flaskapp Flask(__name__)app.route(/) def hello_world():return 欢迎来到我的Python Web程序!if __name__ __main__:app.run(debugTrue)1、安装flask D:\Users\USER\PycharmProjects\pythonProject1\p01>pip install flask WARNING: Ignoring invalid…

服务器五大关键组件拆解分析

拆解服务器五大关键组件 "AI服务器五大硬件揭秘&#xff1a;深入剖析PCB构造&#xff0c;揭示内部真实面貌。本文通过一步步拆解PCB,为读者呈现了一台服务器的内部世界&#xff0c;力求让您对服务器升级的潜在价值有更深的理解和把握。" 1、五大硬件部分可归纳为——…

自定义开屏启动广告页

自定义开屏启动广告页 文章目录 自定义开屏启动广告页效果图简单版轮播方式css 效果图 简单版 图片 倒计时 <template><view class"guide fcc" :style"{ background: url(${ imgUrl }) no-repeat}"><view class"skip_btn" cli…