MybatisPlus最全讲解
一、简介
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
二、快速开始
1.创建一个空的springboot工程
1.添加依赖
<dependencies>
<!--springboot起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--springboot web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatisplus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--代码生成器-->
<dependency><!-- mybatis-plus代码生成器 -->
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!--阿里巴巴数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.8.2</version>
</dependency>
</dependencies>
2.创建代码生成器
创建一个config目录,然后创建一个CodeGenerator类
package com.wjk.config;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import java.util.ArrayList;
import java.util.List;
public class CodeGenerator {
public static void main(String[] args) {
//数据库连接
String url = "jdbc:mysql://localhost:3306/smart_farm?serverTimezone=UTC";//数据库url
String username = "root";//账号
String password = "210278";//密码
String module = "";//项目模块名,如果是有父项目的话,需要配置。
//全局配置参数
String author = "wjk";//作者
String outputDir = System.getProperty("user.dir")+"/"+module+"/src/main/java";//指定输出目录
//包配置参数
String parent = "com.wjk";//父包名
String moduleName = "";//父包模块名
String entity = "entity";//Entity 实体类包名
String mapper = "mapper";//Mapper 包名
String mapperXml = "mapper";//Mapper XML 包名
String service = "service";//Service 包名
String serviceImpl = "service.impl";//Service Impl 包名
String controller = "controller";//Controller 包名*/
//要生成的数据库表
List<String> tables = new ArrayList<>();
tables.add("account");
// tables.add("dep");
// tables.add("phone");
// tables.add("stu");
//开始生成
FastAutoGenerator.create(url,username,password)
//全局配置
.globalConfig(builder -> {
builder.author(author)
.outputDir(outputDir)
.disableOpenDir() //生成之后不打开目录
/*.enableSwagger()//开启swagger*/
.fileOverride() // 覆盖已生成文件,默认为false
.dateType(DateType.ONLY_DATE) //定义生成的实体类中日期类型 DateType.ONLY_DATE 默认值: DateType.TIME_PACK
.commentDate("yyyy-MM-dd");//注释日期
})
//包配置
.packageConfig(builder -> {
builder.parent(parent)
.moduleName(moduleName)
.entity(entity)
.mapper(mapper)
.xml(mapperXml)
.service(service)
.serviceImpl(serviceImpl)
.controller(controller);
})
//策略配置
.strategyConfig(builder -> {
builder.addInclude(tables)
// .addTablePrefix("sys_") // 设置过滤表前缀
//开启生成实体类
.entityBuilder()
.enableLombok()//开启 lombok 模型
.enableTableFieldAnnotation()//开启生成实体时生成字段注解
//开启生成mapper
.mapperBuilder()
//.enableBaseResultMap()//启用 BaseResultMap 生成
.superClass(BaseMapper.class)//设置父类
.enableMapperAnnotation()//开启 @Mapper 注解
.formatMapperFileName("%sMapper")//格式化 mapper 文件名称
.formatXmlFileName("%sMapper")//格式化 xml 实现类文件名称
//开启生成service及impl
.serviceBuilder()
.formatServiceFileName("%sService")//格式化 service 接口文件名称
.formatServiceImplFileName("%sServiceImpl")//格式化 service 实现类文件名称
//开启生成controller
.controllerBuilder()
// 映射路径使用连字符格式,而不是驼峰
//.enableHyphenStyle()
.formatFileName("%sController")//格式化文件名称
.enableRestStyle();
})
.templateEngine(new VelocityTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
//.templateConfig(builder -> builder.controller(""))//关闭生成controller
.execute();
}
}
自动创建百分之九十的结构
三、BaseMapper<>
BaseMapper<> 是一个泛型接口,其作用是提供基础的 CRUD(Create、Retrieve、Update 和 Delete)操作方法。它通常与 MyBatis ORM(Object-Relational Mapping)框架搭配使用,用于简化数据访问层的开发。
通过继承 BaseMapper<User>
接口,UserMapper
接口就可以获得一组默认的 CRUD 方法,如 insert、selectOne 和 delete 等,无需手动编写 SQL 语句
四、使用xxxMapper进行增删改查
1.Insert
// 插入一条记录
int insert(T entity);
2.Delete
根据主键id删除数据(直接传id)----deleteById
int count2 = accountMapper.deleteById(3)
System.out.println("删除了:" + count );
根据主键id批量删除数据----deleteBatchIds
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(4);
accountMapper.deleteBatchIds(ids);
通过构造器删除(wrapper)----delete
QueryWrapper qw = new QueryWrapper<>();
qw.eq("name","wjk");
qw.eq("account_id",2);
//delete from account where (name="wjk" and id = 2)
accountMapper.delete(qw);
lambda表达式
accountMapper.delete(new QueryWrapper<Account>()
// .lambda()
// .eq(Account::getAccountName,"wjk")
// .eq(Account::getAccountId,2)
// );
通过map删除
Map<String,Object> col = new HashMap<>();
// col.put("name","jay");
// col.put("id",12);
int count3 = accountMapper.deleteByMap(col);
// System.out.println(count);
3.Update
根据 ID 修改----updateById
Account account1 = Account.builder()
.accountName("wjk")
.accountId(4)
.password("11111")
.build();
int count4 = accountMapper.updateById(account1);
根据 whereWrapper 条件,更新记录
Account account = Account.builder()
.accountName("wjk")
.accountId(1)
.password("1111")
.build();
UpdateWrapper<Account> updateWrapper = new UpdateWrapper<>();
//eq代表等于
updateWrapper.eq("age",13);
int count = accountMapper.update(account,updateWrapper);
4.Select
根据 ID 查询----selectById
Account account2 = accountMapper.selectById(2);
通过构造wrapper条件查询一条数据----selectOne
QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
//设置查询字段;仅查询name和id字段
queryWrapper.select("id","name");
//添加查询条件
queryWrapper.eq("id",5);
account2 = accountMapper.selectOne(queryWrapper);
根据id进行批量查询----selectBatchIds
List<Account> accountList = accountMapper.selectBatchIds(Arrays.asList(1,2,3));
通过wrapper组装查询条件,查询全部数据----selectList
QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
accountQueryWrapper.select("id","name");//只查询id和name字段
//添加查询条件
queryWrapper.eq("age",30);
List<Account> accountList1 = accountMapper.selectList(queryWrapper);
通过map查询----selectByMap
Map<String,Object> colMap = new HashMap<>();
colMap.put("name","wjk");
colMap.put("age",13);
List<Account> accountList2 = accountMapper.selectByMap(colMap);
根据wrapper条件,查询记录总数----selectCount
QueryWrapper<Account> queryWrapper1 = new QueryWrapper<>();
queryWrapper.eq("name","xx").eq("age",13);
long count6 = accountMapper.selectCount(queryWrapper1);
多表关联查询----selectOrders()
// 需求:假设前端需要展示数据:订单号、商品名称、商品价格、下单用户名、下单用户年龄、性别
// select o.order_id,o.user_id,o.goods_name,o.goods_price,u.name,u.age,u.gender from t_order as o left join t_user as u on o.user_id=u.id
// List<OrderVo> orderVos = userMapper.selectOrders();
// orderVos.forEach(System.out::println);
关联分页查询
// 关联分页查询
//查询第一页,每页数据显示10条
// Page<OrderVo> page = new Page<>(1,10);
// // 手动关闭sql优化,不然查询总数的时候只会查询主表
// page.setOptimizeCountSql(false);
//
// //组装插叙你条件 age = 30
// QueryWrapper<OrderVo> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("age",30);
//
// IPage<OrderVo> page1 = userMapper.selectOrderPage(page,queryWrapper);
// System.out.println("总记录数:" + page1.getTotal());
// System.out.println("总共页数:" + page1.getPages());
// System.out.println("当前页码:" + page1.getCurrent());
// System.out.println("当前查询数据:" + page1.getRecords());
五、使用xxxService进行增删改查
1.Save(增加)
save
/**
// * service层新增 save
// * 参数:实体类
// * 返回类型:boolean
// */
Account account2 = new Account();
// account2.setAccountName("wjk");
// account2.setPassword("123456");
// account2.setAccountId(9);
// boolean isSuccess2 = accountService.save(account2);
批量插入:saveBatch()
/**
// * 为批量插入:saveBatch()
// * 参数:集合
// * 返回类型:boolean
// */
List<Account> accountList = new ArrayList<>();
// for(int i = 1;i<5;i++){
// Account account3 = new Account();
// account3.setAccountName("wjk");
// account3.setPassword("12345678");
// accountList.add(account3);
// }
// boolean isSuccess = accountService.saveBatch(accountList);
批量保存或更新:saveOrUpdateBatch()
/**
// * 批量保存或更新:saveOrUpdateBatch()
// * 参数:集合
// * 返回类型:boolean
// */
//如果实体对象的主键已存在,则执行更新操作;如果主键不存在,则执行插入操作
// List<Account> accountList1 = new ArrayList<>();
// for(int i = 1;i<5;i++){
// Account account4 = new Account();
// account4.setAccountName("wjk");
// account4.setPassword("12345678");
// accountList.add(account4);
// }
// boolean isSuccess3 = accountService.saveOrUpdateBatch(accountList1);
// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
2.Remove(删除)
// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);
3.Get(查询)
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
4.分页查询
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
六、逻辑删除
要求移除某个对象,可是不删除数据库中的数据,以便进行数据恢复
1、何为逻辑删除?
逻辑删除是指文件或者数据没有被真正的删除,只不过通过对数据进行标注,从而让数据无法被识别到。通常这种删除操作是可逆的,就是说用适当的工具或软件可以把删除的文件或者数据恢复出来。
2、使用说明:
只对自动注入的 sql 起效,自己在mapper.xml中写的sql不生效:
插入: 不作限制
查找: 追加 where 条件过滤掉已删除数据
更新: 追加 where 条件防止更新到已删除数据
删除: 转变为更新
3、 yml配置
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 全局逻辑删除的实体字段名,也可实体类字段上加上@TableLogic注解
logic-delete-value: 1 # 逻辑已删除值
logic-not-delete-value: 0 # 逻辑未删除值
4.@TableLogic注解
假如在查询的时候不想查询该字段,可以在字段上加上 @TableField(select = false)注解