Mybatis Plus
- 官网:daomidou.com 苞米豆
- 去官网看指南,就是课件了
简介
- MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
项目搭建
-
创建项目后,引入依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency>
-
可以安装MybatisX插件
-
配置文件 配置数据源
# DataSource Config spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/student username: root password: 111111 mybatis-plus: mapper-locations: mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #在mybatis-plus中下划线转驼峰默认是开启的 map-underscore-to-camel-case: true #全局配置 global-config: #数据库相关配置 db-config: #主键生成策略的全局配置 id-type: assign_id #表的前缀 # table-prefix: tbl_
-
实体类,使用注解 描述对应关系
-
全局配置 局部配置
-
标记表名
-
标记字段名
-
设置主键
- 主键自增(由数据库自增)
- 主键默认值
@Data @Accessors(chain = true) //@TableName("tbl_user") public class User { /** * 实体属性与表中主键字段对应 * type配置项,设置主键生成策略 * type = IdType.AUTO 数据库主键自增 * type = IdType.ASSIGN_ID 默认值,表示当前主键值,由MybatisPlus生成,采用雪花算法(主键类型为varchar,bigint) * type = IdType.ASSIGN_UUID 表示当前主键值,由MybatisPlus生成,采用UUID */ // @TableId(value = "id",type = IdType.AUTO) // @TableId(value = "id",type = IdType.ASSIGN_ID) // @TableId(value = "id",type = IdType.ASSIGN_UUID) private String id; //实体属性与表非主键字段对应 @TableField("name") private String userName; private Integer age; private String email; //非表中字段 @TableField(exist = false) private String genderName; }
-
-
Dao层
/** * 在MybatisPlus中dao接口无需定义任何的抽象方法,继承BaseMapper<实体类型>的父接口就可以了 */ @Mapper public interface UserDao extends BaseMapper<User> { }
-
Mapper层,可以省略,不用写
-
测试
@SpringBootTest class Springboot12MybatisPlusApplicationTests { @Autowired UserDao userDao; @Test void testUserList() { List<User> userList = userDao.selectList(null); for (User user : userList) { System.out.println(user); } } @Test void testUserInsert(){ int result = userDao.insert(new User().setUserName("ccc").setAge(23).setEmail("ccc@qq.com")); System.out.println(result); } }
CRUD的实现
Dao层的CRUD
-
自动获取empDao的两种方式
-
接口上使用 @Mapper注解
@Mapper public interface EmpDao extends BaseMapper<Emp> { // void test(); }
-
配置类上使用 @MapperScan,这个插件会报错,但是不影响使用
@SpringBootApplication //@MapperScan(basePackages = "com.dx.dao") //接口上使用@Mapper就可以了 public class Springboot12MybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(Springboot12MybatisPlusApplication.class, args); } }
-
-
增删改查Demo
@SpringBootTest public class MapperTests { @Autowired EmpDao empDao; @Test void test(){ System.out.println(empDao); } @Test void testInsert(){ Emp emp = new Emp(); emp.setEname("张三"); emp.setJob("职员"); emp.setHiredate(new Date()); emp.setSal(5600.0); emp.setDeptno(10); int result = empDao.insert(emp); //MybatisPlus自动开启主键返回功能 System.out.println("主键值:" + emp.getEmpno()); System.out.println(result); } @Test void testUpdate(){ //根据实体对象中的成员变量的值来判断哪些列是需要更新的(属性值为null,则不更新) Emp emp = new Emp(); emp.setEmpno(7945); emp.setEname("李四"); emp.setJob("经理"); empDao.updateById(emp); } @Test void testDelete(){ // empDao.deleteById(1); // empDao.deleteBatchIds(Arrays.asList(1,2,3,4)); Map<String, Object> map = new HashMap<>(); map.put("deptno", 100); empDao.deleteByMap(map); } @Test void testSelectSingle(){ Emp emp = empDao.selectById(7945); System.out.println(emp); } @Test void testSelectList(){ List<Emp> emplist = empDao.selectList(null); for (Emp emp : emplist) { System.out.println(emp); } } @Test void testSelectByMap(){ Map<String, Object> map = new HashMap<>(); map.put("job", "SALESMAN"); map.put("deptno", 10); List<Emp> empList = empDao.selectByMap(map); for (Emp emp : empList) { System.out.println(emp); } } }
Service层的CRUD
-
传统的需要依赖注入
-
现在继承接口直接用提供的属性就可以
-
/** * 在MybatisPlus中提供一个IService<实体类类型>的父接口 * 在service接口也可扩展自己的方法 */ public interface EmpService extends IService<Emp> { //扩展方法 void test(); }
/** * 在MybatisPlus的Service实现类中需要继承一个父类ServiceImpl<持久层接口类型, 实体类类型> */ @Service public class EmpServiceImpl extends ServiceImpl<EmpDao, Emp> implements EmpService { // @Autowired // private EmpDao empDao; @Override public void test() { //在Service层中调用dao // empDao.selectList(null); // this.baseMapper.selectList(null); // this.baseMapper.test(); } }
-
测试Demo 自动注入
@SpringBootTest public class ServiceTests { @Autowired private EmpService empService; //...... }
-
新增数据
@Test void testSave(){ Emp emp = new Emp(); emp.setEname("zhangsan"); emp.setJob("zhiyuan"); emp.setHiredate(new Date()); emp.setSal(5600.0); emp.setDeptno(10); boolean result = empService.save(emp); System.out.println(result); }
-
更新数据
@Test void testUpdate(){ Emp emp = new Emp(); emp.setEmpno(7946); emp.setEname("wangwu"); emp.setJob("aaaaaaa"); empService.updateById(emp); }
-
删除数据
@Test void testRemove(){ empService.removeById(7499); }
-
查询数据
@Test void testGet(){ Emp emp = empService.getById(7946); System.out.println(emp); } @Test void testList(){ List<Emp> empList = empService.list(); for (Emp emp : empList) { System.out.println(emp); } } @Test void testCount(){ long total = empService.count(); System.out.println(total); }
条件构造器查询
-
条件构造器
-
用于写where后面的条件
-
条件:大于 小于 between like …
-
使用条件查询器
/** * 条件查询中使用的条件构造器 */ @Test void testWrapper(){ Integer deptno = 10; Double sal = 1500.0; String ename = "S"; QueryWrapper<Emp> queryWrapper = new QueryWrapper<>(); queryWrapper.select("empno", "ename", "job"); /** * eq(查询字段名, 字段值) * eq(条件, 查询字段名, 字段值) */ queryWrapper.eq(deptno!=null, "deptno", deptno); queryWrapper.ge(sal!=null, "sal", sal); queryWrapper.like(StringUtils.hasLength(ename), "ename", ename); queryWrapper.orderBy(true, false, "sal"); empService.list(queryWrapper); }
-
扩展
逻辑删除
-
物理删除:使用delete
delete from tbl_emp where empno=1;
-
逻辑删除:更改表中设计的删除标志的字段,使用updata
-
-- 1.需要在表中设计一个字段(删除标志) 0表示数据正常 1数据删除 -- 2.查询时必须携带删除标志字段的条件 select * from tbl_emp where del_flag=0; -- 3.删除时仅需更新删除标志字段的值为1即可 update tbl_emp set del_flag=1 where empno=7369;
-
配置逻辑删除标志
/** * @TableLogic 注解是逻辑删除,实体类加上这个注解再执行删除方法的时候会变成修改 */ @TableLogic private String delFlag;
-
分页插件
-
配置类配置分页插件
@Configuration public class MybatisPlusConfig { /** * 分页插件配置 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
-
测试
/** * 分页查询 */ @Test void testPage(){ /** * page(分页设置对象, 分页时条件查询器) */ Page<Emp> page = new Page<>(1, 5); IPage<Emp> iPage = empService.page(page); //当前页列表数据 List<Emp> empList = iPage.getRecords(); for (Emp emp : empList) { System.out.println(emp); } System.out.println("当前页码:" + iPage.getCurrent()); System.out.println("每页条数:" + iPage.getSize()); System.out.println("总记录数:" + iPage.getTotal()); System.out.println("总页数:" + iPage.getPages()); System.out.println("是否存在上一页:" + ((Page<Emp>)iPage).hasPrevious()); System.out.println("是否存在下一页:" + ((Page<Emp>)iPage).hasNext()); }
非表字段注解
- 实体类的非表字段标注
/** * @TableField(exist=false) :表示该属性不为数据库表字段 */ @TableField(exist = false) private String str;