当前位置: 首页 > news >正文

Mybatis Plus框架 基本语法

MybatisPlus 中文官网

依赖配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>Demo project for Spring Boot</description><properties><java.version>8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--MybatisPlus官方提供的starter,其中集成了Mybatis以及plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><!-- 代码生成器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.4.1</version></dependency><!-- Apache Velocity --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version></dependency><!-- @ApiModel等注解对应依赖 --><dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>1.5.13</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

数据库连接

#设置开发环境 @Profile指定
#spring.profiles.active=dev#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456#配置日志:Sql如何执行的
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl#mybatis plus逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

注解

package com.example.entity;import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user")
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;@TableField(value = "name")private String name;private Short age;private Short gender;private String phone;@Versionprivate Integer version;//对于字段is前缀的需要使用注解绑定@TableField(value = "is_deleted")@TableLogicprivate Integer isDeleted;//首次时间是插入,之后是更新@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;@TableField(fill = FieldFill.INSERT)private Date createTime;
}

CRUD接口

在这里插入图片描述
Lambda条件构造器使用原因:
QueryWrapper、UpdateWrapper条件构造器都是用字符串的形式指定。这种方式无法在编译期确定列名的合法性。

Wrapper 注意

条件调用 如果不写.select(XX,XX),默认就是select* 

自动填充

package com.example.handler;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.util.Date;@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill ....");this.setFieldValByName("createTime", new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ....");this.setFieldValByName("updateTime",new Date(),metaObject);}
}

乐观锁和分页插件

package com.example.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.aop.interceptor.PerformanceMonitorInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;// Spring Boot 方式
@Configuration
public class MybatisPlusConfig {/*** 新版 注册乐观锁插件*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加return mybatisPlusInterceptor;}/*  //分页插件@Beanpublic PaginationInnerInterceptor pageInterceptor(){return new PaginationInnerInterceptor();}*/}

Mapper层

说明:/*通用 CRUD 封装BaseMapper (opens new window)接口,为 Mybatis-Plus启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器 */
public interface UserMapper extends BaseMapper<User> {}
package com.example;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.entity.User;
import com.example.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.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@SpringBootTest
class DemoApplicationTests {//UserMapper集成BaseMapper所有方法,也可以自定义@Autowiredprivate UserMapper userMapper;@Testvoid contextLoads() {//wrapper:条件构造器//查询所有用户List<User> userList = userMapper.selectList(null);userList.stream().forEach(user -> System.out.println(user));}//批量查询 In@Testpublic void selectByIds(){List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));users.stream().map(user -> user.getName()).forEach(user -> System.out.println(user));}//Map查询:条件查询@Testpublic void selectByMap(){Map<String, Object> map = new HashMap<>();map.put("name","圆圆");List<User> users = userMapper.selectByMap(map);users.stream().map(user -> user.getName()).forEach(user -> System.out.println(user));}//Wrapper查询:类比Map条件查询@Testpublic void selectByWrapper(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.ge("age","1").eq("phone","123456");userMapper.selectList(queryWrapper).stream().map(user -> user.getName()).forEach(e -> System.out.println(e));}//分页查询@Testpublic void selectPage(){//参数1:当前页面    参数2:页面大小Page<User> page = new Page<>(3,3);  //limit 6,3userMapper.selectPage(page,null);page.getRecords().stream().forEach(user -> System.out.println(user));}@Testpublic void insert(){User user = new User();user.setName("元宝");user.setAge((short)1);user.setGender((short)1);user.setPhone("123456");int i = userMapper.insert(user);System.out.println("插入结果:"+i);}//乐观锁测试 version初始值为1@Testpublic void testOptimisticLocker(){User user1 = userMapper.selectById(11);user1.setPhone("2444");User user2 = userMapper.selectById(11);user2.setPhone("2555");userMapper.updateById(user2);//执行失败,version=2userMapper.updateById(user1);}@Testpublic void deleteById(){userMapper.deleteById(12);}//只能更新一条记录//UPDATE user SET age=? ,updateTime=? WHERE is_deleted=0 AND (id < ?)@Testpublic void update1(){User user = new User();user.setId(10);user.setAge((short)20);//在调用updateById方法前,需要在T entity(对应的实体类)中的主键属性上加上@TableId注解。userMapper.updateById(user);}//可以更新一批对象,更为细致地设置具体字段// UPDATE user SET age=? WHERE is_deleted=0 AND (id < ?)@Testpublic void update2(){UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();updateWrapper.lt("id",11);updateWrapper.set("age",20);userMapper.update(null,updateWrapper);}/*Lambda条件构造器使用原因:之前使用条件构造器都是用字符串的形式指定。这种方式无法在编译期确定列名的合法性。*///查询@Testpublic void select(){LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(User::getAge,20);List<User> users = userMapper.selectList(queryWrapper);users.stream().forEach(e -> System.out.println(e));}}

Service CRUD 接口

/*
- 通用 Service CRUD 封装IService (opens new window)接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,
- 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类
对象 Wrapper 为 条件构造器
*/
public interface UserService extends IService<User> {//自定义方法List<String> test();}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {/*技巧:操作一个对应的表直接使用getBaseMapper()操作其他表@Autowired注入*/@Overridepublic List<String> test() {UserMapper userMapper = getBaseMapper();List<User> userList = userMapper.selectList(new QueryWrapper<User>()  //在userMapper.selectList()方法中不能使用LambdaQueryWrapper.lambda().eq(User::getAge, 20));List<String> list = userList.stream().map(e -> e.getName()).collect(Collectors.toList());return list;}
}

Controller层

 @Autowired //将service接口注入private EmployeeService employeeService;/*** 员工登录* @param request 将员工id存到session中* @param param 前端传来JSON形式数据,使用@RequestBody接收* @return*/@PostMapping("/login")public void login(HttpServletRequest request, @RequestBody Employee param){/***  SELECT*  name,phone*  FROM employee*  WHERE name = 'xxx' AND password = 'xxx' AND id > 1000 AND (update_time between 'xxx' AND 'xxxx') AND*  ORDER BY create_time DESC limit 1;* */LambdaQueryWrapper<Employee> queryWrapper = new QueryWrapper<Employee>()  .lambda().select(Employee::getName , Employee::getPhone)  //条件默认用AND连接.eq(Employee::getName ,param.getName()).eq(Employee::getPassword , param.getPassword()).ne(Employee::getStatus , 2).ge(Employee::getId , 1000).between(Employee::getUpdateTime , "2023-09-10" , "2023-10-10").orderByDesc(Employee::getCreateTime).last("limit 1");    //如果有多个数据,只获取一个。类似数据库中的unique。Employee employee1 = employeeService.getOne(queryWrapper);  //getOne():获取一条结果employeeService.getOne(new QueryWrapper<Employee>().lambda().select(Employee::getName , Employee::getPhone).eq(Employee::getName ,param.getName()).eq(Employee::getPassword , param.getPassword()).last("limit 1"));//查询phone是182开头、或者 (name以王开头 并且 用户状态是1)//SELECT XXX FROM xx WHERE (phone like 182) OR (name LIKE 王 AND status = 1)//王 2employeeService.list(new QueryWrapper<Employee>().lambda().likeLeft(Employee::getPhone , "182") //182XXX。likeLeft和likeRigt查询效率高。.or(e -> e.likeLeft(Employee::getName , "王").eq(Employee::getStatus , 1)) //这里e指代new QueryWrapper<Employee>对象);/*List<Employee> employeeList = new ArrayList<>();employeeList.stream().filter(e -> e.getName().equals("王子怡")); //这里e 代表Employee对象。如果有List类型,就代表集合元素*/}

代码生成器

package com.example.demo;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;/*** @author* @since 2018/12/13*/
@Slf4j
public class CodeGenerator {@Testpublic void run() {// 1、创建代码生成器AutoGenerator mpg = new AutoGenerator();// 2、全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath + "/src/main/java");gc.setAuthor("Vivi"); //需要手动修改!gc.setOpen(false); //生成后是否打开资源管理器gc.setFileOverride(false); //重新生成时文件是否覆盖gc.setServiceName("%sService");    //去掉Service接口的首字母Igc.setIdType(IdType.ASSIGN_ID); //主键策略gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型gc.setSwagger2(true);//开启Swagger2模式mpg.setGlobalConfig(gc);// 3、数据源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8"); //需要手动修改!dsc.setDriverName("com.mysql.cj.jdbc.Driver");dsc.setUsername("root"); //需要手动修改!dsc.setPassword("123456");  //需要手动修改!dsc.setDbType(DbType.MYSQL);mpg.setDataSource(dsc);// 4、包配置PackageConfig pc = new PackageConfig();pc.setModuleName("project1"); //模块名 需要手动修改!pc.setParent("com.example.demo");  //需要手动修改!pc.setController("controller");pc.setEntity("entity");pc.setService("service");pc.setMapper("mapper");mpg.setPackageInfo(pc);// 5、策略配置StrategyConfig strategy = new StrategyConfig();strategy.setInclude("user"); //表名 需要手动修改!strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略//strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作strategy.setRestControllerStyle(true); //restful api风格控制器strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符mpg.setStrategy(strategy);// 6、执行mpg.execute();}
}

代码模板

@Overridepublic PageResult<EmployeeListVO> pageEmployee(HrEmployeeRequest hrEmployeeRequest) {LambdaQueryWrapper<HrEmployee> wrapper = createWrapper(hrEmployeeRequest);//创建时间倒序wrapper.orderByDesc(HrEmployee::getCreateTime);wrapper.select(HrEmployee::getEmployeeId , HrEmployee::getEmployeeName , HrEmployee::getPhone);Page<HrEmployee> sysRolePage = this.page(PageFactory.defaultPage(), wrapper);//提取List并转成对应的VOList<HrEmployee> employeePageList = sysRolePage.getRecords();List<EmployeeListVO> employeeVOList = BeanUtil.copyToList(employeePageList , EmployeeListVO.class);//提取这一批数据的员工id集合List<Long> employeeIdList = employeePageList.stream().map(e -> e.getEmployeeId()).collect(Collectors.toList());//从hr_employee_org关系表 提取这一批员工的主要组织机构 + 主要部门 + 主要任职岗位List<EmployeeOrg> relationList = employeeOrgService.list(new QueryWrapper<EmployeeOrg>().lambda().eq(EmployeeOrg::getMainFlag , YesOrNotEnum.Y.getCode()).in(EmployeeOrg::getEmployeeId , employeeIdList));Map<Long , EmployeeOrg> relationMap = new HashMap<>();Map<Long , String> orgMap = new HashMap<>();Map<Long , String> departmentMap = new HashMap<>();Map<Long , String> positionMap = new HashMap<>();if (!relationList.isEmpty()) {//转map,备用relationMap = relationList.stream().collect(Collectors.toMap(e -> e.getEmployeeId() , Function.identity() , (e1 , e2) -> e2));//提取组织机构、部门、任职岗位信息List<Long> orgIdList = relationList.stream().map(e -> e.getOrgId()).collect(Collectors.toList());List<Long> departmentIdList = relationList.stream().map(e -> e.getDepartmentId()).collect(Collectors.toList());List<Long> positionIdList = relationList.stream().map(e -> e.getPositionId()).collect(Collectors.toList());//组织机构信息List<HrOrganization> orgList = hrOrganizationService.list(new QueryWrapper<HrOrganization>().lambda().select(HrOrganization::getOrgId , HrOrganization::getOrgName).in(HrOrganization::getOrgId , orgIdList));orgMap = orgList.stream().collect(Collectors.toMap(e -> e.getOrgId() , e -> e.getOrgName() , (e1,e2) -> e2));//部门信息List<HrOrganization> departmentList = hrOrganizationService.list(new QueryWrapper<HrOrganization>().lambda().select(HrOrganization::getOrgId , HrOrganization::getOrgName).in(HrOrganization::getOrgId , departmentIdList));departmentMap = departmentList.stream().collect(Collectors.toMap(e -> e.getOrgId() , e -> e.getOrgName() , (e1,e2) -> e2));//职位信息List<HrPosition> positionList = hrPositionService.list(new QueryWrapper<HrPosition>().lambda().select(HrPosition::getPositionId , HrPosition::getPositionName).in(HrPosition::getPositionId , positionIdList));positionMap = positionList.stream().collect(Collectors.toMap(e -> e.getPositionId() , e -> e.getPositionName() , (e1,e2) -> e2));}//TODO 提取员工的登录账号List<EmployeeUser> accountRelationList = employeeUserService.list(new QueryWrapper<EmployeeUser>().lambda().in(EmployeeUser::getEmployeeId , employeeIdList));Map<Long , EmployeeUser> accountRelationMap = new HashMap<>();if (!accountRelationList.isEmpty()) {accountRelationMap = accountRelationList.stream().collect(Collectors.toMap(e -> e.getEmployeeId() , Function.identity() , (e1 , e2) -> e2));}//遍历一遍,设置关联字段的属性值for (EmployeeListVO vo : employeeVOList) {//从关系map提取当前员工的数据EmployeeOrg relation = relationMap.get(vo.getEmployeeId());if (relation == null) {continue;}vo.setOrgName(orgMap.get(relation.getOrgId()));vo.setDepartmentName(departmentMap.get(relation.getDepartmentId()));vo.setPositionName(positionMap.get(relation.getPositionId()));}//复制分页信息,绑定ListPage<EmployeeListVO> employVOPage = new Page<>();BeanUtil.copyProperties(sysRolePage , employVOPage);employVOPage.setRecords(employeeVOList);return PageResultFactory.createPageResult(employVOPage);}

相关文章:

  • SpringBoot整合JdbcTemplate
  • 二进制安装docker
  • 测试开发实习岗---测试用例
  • Mysql整理-高级特性
  • iOS调起高德/百度/腾讯/谷歌/苹果地图并使用GCJ02坐标进行导航
  • 鸡尾酒疗法 T1067
  • 文物预防性保护系统方案的需求分析
  • C语言中的字符魔法:大小写转换的艺术
  • Android 基础入门 基础简介
  • vue模板语法中的类和样式绑定
  • midjourney提示词语法
  • Some collections -- 2024.3
  • YOLOv8基础必需运用【目标检测、分割、姿势估计、跟踪和分类任务】
  • Nginx反向代理与负载均衡
  • 2023 版王道单科书勘误汇总(3.30)
  • php的引用
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • Angular数据绑定机制
  • ES6核心特性
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • node入门
  • SQLServer插入数据
  • Webpack 4 学习01(基础配置)
  • web标准化(下)
  • 安装python包到指定虚拟环境
  • 安卓应用性能调试和优化经验分享
  • 对JS继承的一点思考
  • 坑!为什么View.startAnimation不起作用?
  • 模型微调
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 责任链模式的两种实现
  • 阿里云ACE认证学习知识点梳理
  • ​什么是bug?bug的源头在哪里?
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (16)Reactor的测试——响应式Spring的道法术器
  • (LeetCode C++)盛最多水的容器
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • .apk 成为历史!
  • .NET/C# 使用反射注册事件
  • .Net语言中的StringBuilder:入门到精通
  • ?
  • @kafkalistener消费不到消息_消息队列对战之RabbitMq 大战 kafka
  • [].shift.call( arguments ) 和 [].slice.call( arguments )
  • [20150629]简单的加密连接.txt
  • [2021 蓝帽杯] One Pointer PHP
  • [C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改
  • [C#] 如何调用Python脚本程序
  • [C++]模板与STL简介
  • [CLR via C#]11. 事件
  • [codevs] 1029 遍历问题
  • [ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-controller-manager失败
  • [java刷算法]牛客—剑指offer链表有环的入口、反转链表、合并排序链表