目录
含义:mybatis-plus是个mybatis的增强工具,在mybatis的基础上只做增强不做改变,为简化开发,提高效率而生
注意:我们可以直接在mybatis的基础上直接去集成mybatisplus,这样并不会影响mybatis的功能,同时我们也可以使用他所提供的功能。

理解:
- <dependencies>
- <!--springboot启动器-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
- <!--springboot测试-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <!--lombok依赖-->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
- <!--MP启动器-->
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- <version>3.5.1</version>
- </dependency>
- <!--mysql驱动包--><!--测试功能的启动器-->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <scope>runtime</scope>
- </dependency>
- </dependencies>
- spring:
- #设置数据源信息
- datasource:
- #配置数据源类型
- type: com.zaxxer.hikari.HikariDataSource
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql:///mybatis_plus?characterEncoding=utf-8&userSSL=false&serverTimezone=GMT%2B8
- username: root
- password: root
- mybatis-plus:
- configuration:
- #MP提供了日志功能
- log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
- #驼峰映射(默认就是开启的)
- map-underscore-to-camel-case: true
- #设置MP的全局配置
- global-config:
- db-config:
- #这样设置的话,那么实体类所有的表都会加上t_前缀
- table-prefix: t_
- #设置统一主键生成策略
- id-type: auto
- #映射文件路径
- mapper-locations: classpath:/mapper/UserMapper.xml
- #配置类型别名所对应的包
- type-aliases-package: cn.tedu.mybatisplus.pojo
- #扫描通用枚举的包
- type-enums-package: cn.tedu.mybatisplus.enums
- //使用MP提供的通用mapper——BaseMapper
- //BaseMapper里的泛型表示实体类的类型
- @Mapper
- public interface UserMapper extends BaseMapper<User> {
- }
注意:
注意:使用前注入userMapper
- User user = new User();
- user.setName("lili").setAge(23).setEmail("lili@qq.com");
- int insert = userMapper.insert(user);
- System.out.println(insert);
- //mybatis-plus会自动获取id
- System.out.println(user.getId());
- int i = userMapper.deleteById(7);
- System.out.println(i);
- Map<String,Object> map=new HashMap<>();
- map.put("name", "张三");
- map.put("age", 23);
- //删除name为张三,age为23的人
- int i = userMapper.deleteByMap(map);
- System.out.println(i);
- List<Long> list = Arrays.asList(1L, 2L, 3L);
- int i = userMapper.deleteBatchIds(list);
- System.out.println(i);
- User user = new User();
- user.setId(3L).setName("lan").setEmail("lan@qq.com");
- //根据id修改元素
- int i = userMapper.updateById(user);
- System.out.println(i);
- User user = userMapper.selectById(1L);
- System.out.println(user);
- List<Long> list = Arrays.asList(1L, 2L, 3L);
- List<User> users = userMapper.selectBatchIds(list);
- users.forEach(System.out::println);
- HashMap<String, Object> map = new HashMap<>();
- map.put("name", "lan");
- map.put("age", 28);
- List<User> users = userMapper.selectByMap(map);
- //list会直接打印对象数组
- System.out.println(users);
说明:通用Service封装了IService接口,进一步封装了CRUD采用get查询单行,remove删除,list查询集合,page分页等前缀命名方式,区分Mapper层,避免混淆
- //service接口
- public interface UserService extends IService<User> {
- }
- //service实现类
- @Service
- public class UserServiceImpl extends ServiceImpl
, User> implements UserService { - }
注意:
- //查询总记录数
- long count = userService.count();
- System.out.println(count);
- ArrayList<User> list = new ArrayList<>();
- for (int i = 1; i <=10 ; i++) {
- User user = new User();
- user.setName("cjc"+i).setAge(10+i);
- list.add(user);
- }
- //批量添加数据
- boolean b = userService.saveBatch(list);
- //操作成功或失败
- System.out.println(b);
- //设置实体类所对应的表名,若对象与表名一致,则表名中()可以省略
- @TableName("t_user")
- public class User {
- //将当前属性对应的字段指定为主键(将该属性与数据库中的id字段进行映射),并通过雪花算法生成主键id
- //type标识主键的生成策略为自动递增,要求数据库的主键为自增策略(默认为雪花算法——IdType.ASSIGN.ID)
- @TableId(value = "id")
- private Long id;
- //将该注解标识的属性与数据库中的name字段一一映射,若属性名与字段名相同,则注解可省略
- @TableField(value = "name")
- private String name;
- private Integer age;
- private String email;
- //逻辑删除0标识未删除,1标识已删除
- //被逻辑删除的数据用户查不到,但是可以在数据库中看到,只是该属性变为1;(为修改操作)
- @TableLogic
- private Integer isDeleted;
- }
注意:@TableField(exit=false)注解一般用在注入的属性上,被该注解标识表名当前属性不参与MP的操作
背景:需要合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量
数据库表的扩展方式:业务分库、主从复制、数据库分表
数据库分表的两种方式

将重要的数据放到一个表中,不在业务查询中用到的独立到另一个表中,以提升一定的性能
主键自增:比如按照范围分表(1-9999放入表一,10000-20000放入表二)
取模:主键%数据库个数,余数相同的放入一个表中
雪花算法:
雪花算法是由Twitter分布式主键生成算法,他保证不同表的主键的不重复性,以及相同表的主键的有序性
核心思想:

优点:整体上按照时间自增排序,并且整个分布式系统内不会产生id碰撞
作用:封装当前的条件

AbstractWrapper:用于条件查询封装,生成sql的where条件
AbstractLambdaWrapper
- //通过条件构造器查询一个list集合,若没有条件则可以设置null(相当于查询所有)
- List<User> users = userMapper.selectList(null);
- users.forEach(System.out::println);
- //查询name为lei的主键字段
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("name", "lei");
- List
- System.out.println(list);
- //查询用户名包含a,年龄在20-30之间,邮箱信息不为null的用户信息
- QueryWrapper<User> queryWrapper = new QueryWrapper<>();
- //queryWrapper可以实现链式加载
- queryWrapper.like("name", "a").between("age", 20, 30).isNotNull("email");
- List<User> users = userMapper.selectList(queryWrapper);
- System.out.println(users);
- //对象形式
- User user = new User();
- user.setAge(28);
- QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
- List<User> users = userMapper.selectList(queryWrapper);
- System.out.println(users);
- //user内的属性最终会以and形式拼接
- //in查询,查询id为1,2,3的数据
- Integer[] ids={1,2,3};
- QueryWrapper<User> queryWrapper = new QueryWrapper<>();
- queryWrapper.in("id",ids);
- List<User> users = userMapper.selectList(queryWrapper);
- System.out.println(users);
- //查询id>2的用户,按照年龄降序排序,若年两相同则按照id升序排序
- QueryWrapper<User> queryWrapper = new QueryWrapper<>();
- queryWrapper.gt("id", 2).orderByDesc("age").orderByAsc("id");
- List<User> users = userMapper.selectList(queryWrapper);
- System.out.println(users);
转义字符
- //删除邮箱地址为null的用户信息
- QueryWrapper<User> queryWrapper = new QueryWrapper<>();
- queryWrapper.isNull("email");
- int i = userMapper.delete(queryWrapper);
- System.out.println(i);
- //将年龄>20并且用户名中包含a或邮箱为null的用户进行修改(默认情况下就是and连接)
- //修改条件
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - queryWrapper.gt("age", 20).like("name", "a").or().isNull("email");
- User user = new User();
- user.setName("lei").setEmail("test@cj.com");
- int i = userMapper.update(user, queryWrapper);
- System.out.println(i);
- //将用户名中包含a并且(年龄大于20或邮箱为null)的用户信息进行修改
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - //lambda中的条件优先执行(i就表示条件构造器)
- queryWrapper.like("name", "a").and(i-> i.gt("age", 20).or().isNull("email"));
- User user = new User();
- user.setName("red").setEmail("test@cj.com");
- int i = userMapper.update(user, queryWrapper);
- System.out.println(i);
- //查询出来一个以map为泛型的list集合
- //查询用户名、年龄、邮箱信息
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - queryWrapper.select("name","age","email");
- List
- System.out.println(maps);
- //select * from t_user where id in(select id from t_user where id<=100)
- //查询id<=100的用户信息
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - queryWrapper.inSql("id", "select id from t_user where id<=100");
- List
users = userMapper.selectList(queryWrapper); - System.out.println(users);
- String name=null;
- String age="21";
- //判断字符串是否为null或空串若为返回false,不为返回true
- boolean pn = StringUtils.hasLength(name);
- boolean pa = StringUtils.hasLength(age);
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - //判断属性是否为true,为true则执行该条件,不为则忽略该条件
- queryWrapper.eq(pn,"name",name).eq(pa, "age", age);
- List
users = userMapper.selectList(queryWrapper); - System.out.println(users);
注意:queryWrapper.clear();为清除多余的条件,清除后queryWrapper可以继续使用
- //查询用户名中包含a(年龄>20或邮箱为null)的员工信息
- UpdateWrapper
updateWrapper = new UpdateWrapper<>(); - //修改条件
- updateWrapper.like("name", "a").and(i->i.gt("age", 20).isNull("email"));
- //修改内容
- updateWrapper.set("name", "lala").set("email", "www@cjc.com");
- int i = userMapper.update(null, updateWrapper);
- System.out.println(i);
作用:防止我们太笨,而把字段名写错进而提供了一个函数式接口来访问我们实体类中的某一个属性,当我们把属性访问之后,那么他就可以自动的获取属性所对应的字段名,来当作作为条件的哪个字段
- String name="a";
- Integer ageBegin=null;
- Integer ageEnd=30;
- //主要避免了名称写错进而提供了直接访问表达式::
- LambdaQueryWrapper
lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.like(StringUtils.isNotBlank(name), User::getName,name)
- .ge(ageBegin!=null, User::getAge,ageBegin)
- .le(ageEnd!=null, User::getAge,ageEnd);
- List
users = userMapper.selectList(lambdaQueryWrapper); - System.out.println(users);
- //查询用户名中包含a(年龄>20或邮箱为null)的员工信息
- LambdaUpdateWrapper
updateWrapper = new LambdaUpdateWrapper<>(); - //修改条件
- updateWrapper.like(User::getName, "a").and(i->i.gt(User::getAge, 20).isNull(User::getEmail));
- //修改内容
- updateWrapper.set(User::getName, "lala").set(User::getEmail, "www@cjc.com");
- int i = userMapper.update(null, updateWrapper);
- System.out.println(i);
- @Configuration
- public class MPConfig {
- @Bean
- public MybatisPlusInterceptor mybatisPlusInterceptor(){
- //创建mybatisplus拦截器
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- //向拦截器中添加分页插件
- interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
- return interceptor;
- }
- }
- //测试类内
- //两个参数——当前页页码,每页信息条数
- Page
page = new Page<>(2,3); - //两个参数——分页对象,条件构造器
- userMapper.selectPage(page, null);//因为我对所有的查询所以条件构造器为null——返回值还为page
- //获取当前页数据
- List
records = page.getRecords(); - System.out.println(records);
- //获取总记录数
- long total = page.getTotal();
- System.out.println(total);
- //获取总页数
- long pages = page.getPages();
- System.out.println(pages);
- //是否有下一页
- System.out.println(page.hasNext());
- //是否有上一页
- System.out.println(page.hasPrevious());
- //自定义接口:
- //mybatisplus提供的分页对象,必须为于第一个参数的位置
- Page
selectPageVo(@Param("page") Page page,@Param("age") Integer age) ; -
- //自定义配置文件sql
-
- select id,name,age,email from t_user where age>#{age}
-
- //测试类
- Page
page = new Page<>(2, 2); - userMapper.selectPageVo(page,20);
- //获取当前页数据
- List
records = page.getRecords(); - System.out.println(records);
- //获取总记录数
- long total = page.getTotal();
- System.out.println(total);
- //获取总页数
- long pages = page.getPages();
- System.out.println(pages);
- //是否有下一页
- System.out.println(page.hasNext());
- //是否有上一页
- System.out.println(page.hasPrevious());
- @Data
- public class Product {
- private Long id;
- private String name;
- private Integer price;
- @Version//用来标识乐观锁版本号字段
- private Integer version;
- }
- @Configuration
- public class MPConfig {
- @Bean
- public MybatisPlusInterceptor mybatisPlusInterceptor(){
- //创建mybatisplus拦截器
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- //向拦截器中添加乐观锁插件
- interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
- return interceptor;
- }
- }
注意:下面小王和小李拿的是同一个数据
- //小李查询商品价格
- Product productLi = productMapper.selectById(1);
- System.out.println("小李"+productLi.getPrice());
- //小王查询商品价格
- Product productWang = productMapper.selectById(1);
- System.out.println("小王"+productWang.getPrice());
- //小李将商品价格+50
- productLi.setPrice(productLi.getPrice()+50);
- productMapper.updateById(productLi);
- //小王将商品价格-30
- productWang.setPrice(productWang.getPrice()-30);
- int result = productMapper.updateById(productWang);
- if (result==0){
- //操作失败后重试
- Product productNew = productMapper.selectById(1);
- productNew.setPrice(productNew.getPrice()-30);
- productMapper.updateById(productNew);
- }
实体类中有枚举类型,那么怎么将该枚举类型存入到数据库中呢
- //为该枚举添加注解
- @Getter
- public enum SexEnum {
- MALE(1,"男"),
- FEMALE(2,"女");
- @EnumValue//将注解所标识的属性的值存储到数据库中(因为数据库中存放的是数字)
- private Integer sex;
- private String sexName;
- SexEnum(Integer sex, String sexName) {
- this.sex = sex;
- this.sexName = sexName;
- }
- }
配置通用枚举扫描包
mybatis-plus.type-enums-package=cn.tedu.mybatisplus.enums
将有枚举的对象插入到数据库
- @Component
- public class MyMetaObjectHandler implements MetaObjectHandler {
- @Override
- public void insertFill(MetaObject metaObject) {
- this.setFieldValByName("created", new Date(), metaObject);
- this.setFieldValByName("updated", new Date(), metaObject);
- }
- @Override
- public void updateFill(MetaObject metaObject) {
- this.setFieldValByName("updated", new Date(), metaObject);
- }
- }
- @Data
- @Accessors(chain = true)
- public class Product {
- private Long id;
- private String name;
- private Integer price;
- //在插入数据时自动填充
- @TableField(fill = FieldFill.INSERT)
- private Date created;
- //在插入和更新操作时自动填充
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Date updated;
- @Version//用来标识乐观锁版本号字段
- private Integer version;
- }
- //测试
- Product product = new Product();
- product.setName("cake").setId(3L).setPrice(66);
- int insert = productMapper.insert(product);
- System.out.println(insert);