MyBatisPlus

目录

初级

一.MybatisPlus概述

二.入门案例

1.准备一张表并添加几条信息

2.导入依赖

3.启动类

4.根据表字段信息构建domain实体类

5.加入MybatisPlus和数据库连接的依赖

6.数据库配置信息

7.mapper接口准备

8.测试

三.常用设置

1.设置表映射规则

2.设置主键生成策略

3.设置字段和列名的驼峰映射

4.设置字段映射关系

5.日志

四.基本使用

五.条件构造器

1.概述

2.常用AbstractWrapper方法:

3.常用QueryWrapper方法

4.常用UpdateWrapper方法

5.Lambda条件构造器

六.自定义SQL

1.准备表和实体类

2.2种方式

七.分页查询

1.基本分页查询

2.多表分页查询

八.service层接口(缺)

九.代码生成器

高级

一.自动填充

示例

二.逻辑删除

三.乐观锁

1.乐观锁使用

2.多插件配置问题


初级

一.MybatisPlus概述

二.入门案例

SpringBoot整合MybatisPlus

1.准备一张表并添加几条信息

2.导入依赖

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.zcj</groupId>
    <artifactId>MybatisPlus</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <!--将org.springframework.boot项目作为当前项目的父项目-->
    <parent>
        <artifactId>spring-boot-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.0.5.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--domain实体类快速开发依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--必须要@SpringBootTest-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>
        <!--@SpringBootApplication-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <!--@RunWith和@Test-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <!--@RunWith(SpringRunner.class)中SpringRunner需要这个依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>
        <!--2个日志依赖-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.10.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.10.0</version>
        </dependency>
        <!--=======================================================================-->
        <!--MybatisPlus和数据库连接依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
</project>

3.启动类

package cn;


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//如果不在启动类用这个注解,那么就需要在每个**Mapper接口上加@Mapper注解
@MapperScan("cn.zcj.mapper")
public class MyBatisPlusApp {
    public static void main(String[] args) {
        SpringApplication.run(MyBatisPlusApp.class,args);
    }
}

4.根据表字段信息构建domain实体类

package cn.zcj.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private char sex;
    private String phone;
}

5.加入MybatisPlus和数据库连接的依赖

上文已经加上了

         <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

6.数据库配置信息

7.mapper接口准备

mapper扫描(@Mapper)

package cn.zcj.mapper;

import cn.zcj.domain.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface UserMapper extends BaseMapper<User> {
}

8.测试

package cn.zcj;

import cn.zcj.domain.User;
import cn.zcj.mapper.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@SpringBootTest
@RunWith(SpringRunner.class)
public class oneTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void QueryAll(){
        List<User> userList = userMapper.selectList(null);
        for (User user:userList) {
            System.out.println(user);
        }
    }
}

测试结果

 异常总结:

如果你使用MybatisPlus,那么必须保证数据库里面的表名必须和domain实体类的类名在不区分大小写的情况下完全一致,如果不一致,就会报异常,这个异常的意思是无法从数据库中找到一个与当前domain实体类对应的表。

从下图可以看出:MybatisPlus依赖中导入了Mybayis依赖,由此不难看出,MybatisPlus为了简化开发是在Mybatis的基础上做的增强,而不是修改。

三.常用设置

1.设置表映射规则

默认情况下MybatisPlus操作的表名就是实体类的类名,但是当表名和实体类的类名不一致时就需要我们自己设置映射规则。

具体问题展示:

1.1.单独设置

可以在实体类的类名上加上@TableName注解进行标识。

如果表名为"tb_user",而实体类的名字叫User,那么就可以像下面这样写:

1.2.全局设置表名前缀

一般一个项目表名的前缀都是都是统一风格的,这个时候如果还用@TableName注解去实体类上一个一个的设置映射关系,那就太麻烦了。我们可以在配置文件中通过配置来设置全局的表名前缀。

例如:

如果一个项目中所有的比表名相比于类名都多了个前缀:tb_。就可以在application.yml配置文件中使用如下方法配置:

2.设置主键生成策略

2.1.单独设置

默认情况下使用MybatisPlus插入数据时,如果在我们没有设置主键生成策略的情况下默认的策略是基于雪花算法的自增id。

如果我们需要使用别的策略可以在定义实体类时,在代表主键的字段上加上"@TableId"注解,使用其type属性指定主键生成策略。

例如:需要主键id自动增长,则可以进行如下设置:

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
    //将变量id当成主键,且选定类型为自增
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private char sex;
    private String phone;
}

  案例图:

全部主键策略定义在了枚举类IdType中,IdType 有如下的取值:

AUTO

数据库ID自增,依赖于数据库。该类型请确保数据库设置了ID自增否则无效。

NONE

未设置主键类型。若在代码中没有手动设置主键,则会根据主键的全局策略自动生成(默认的主键全局策略是基于雪花算法的自增ID)。

INPUT

需要手动设置主键,若不设置。插入操作生成SQL语句时,主键这一列的值会是null。

ASSIGN ID

当没有手动设置主键,即实体类中的主键属性为空时,才会自动填充,使用雪花算法。

ASSIGN UUID

当实体类的主键属性为空时,才会自动填充,使用UUID。

2.2.全局设置

mybatis-plus:
  global-config:
    db-config:
      #id生成策略:auto为数据库自增
      id-type: auto

3.设置字段和列名的驼峰映射

由于数据库单词字段用"_"符号分割,而java中用驼峰命名法,默认情况下MybatisPlus会开启字段名列名的驼峰映射,即从经典数据库列名 A_COLUMN (下划线命名)到经典Java属性名aColumn (驼峰命名)的类似映射。如果需要关闭我们可以使用如下配置进行关闭。

mybatis-plus:
  configuration:
    #是否开启自动驼峰命名规则
    map-underscore-to-camel-case: false

【补充】当实体类中有驼峰命名的字段,例如userName,那么在SQL在进行查询的时候,如果自动驼峰命名规则没有关闭(默认开启),那么实体类中的userName会被映射成SQL语句中的user_name字段,即:

SELECT user_name FROM `tb_user`

4.设置字段映射关系

默认情况下MybatisPlus会根据实体类的属性名去映射表的列名。如果数据库的列表和实体类的属性名不一致了 我们可以使用@TableFie1d注解的value属性去设映射关系。例如:如果表中一个列名叫phone而实体类中的属性名为Peoplephone则可以使用如下方式进行配置。

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private char sex;
    @TableField("phone")
    private String Peoplephone;
}

【注意】integer太短,不能容纳20位数 ,故将id改为Long类型。

5.日志

如果需要打印MybatisPlus操作对应的SQL语句,可以配置日志输出。

配置如下:

mybatis-plus:
  configuration:
    #日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

案例图:

四.基本使用

1.插入数据操作

用insert方法来实现数据的插入操作

示例:

@Test
public void insert(){
    User user = new User();
    user.setName("随风的风车");
    user.setPeoplephone("1111111111");
    int i = userMapper.insert(user);
    System.out.println("受影响的行数为:"+i+"行");
}

2.删除数据操作

使用deleteXXX方法来实现数据的删除

示例:

//批量删除
@Test
public void batchDelete(){
    ArrayList<Long> ids = new ArrayList<>();
    ids.add(1586908709109440517L);
    ids.add(1586908709109440518L);
    ids.add(1586908709109440519L);
    int i = userMapper.deleteBatchIds(ids);
    System.out.println("受影响的行数为:"+i+"行");
}
//根据id删除
@Test
public void deleteById(){
    int i = userMapper.deleteById(4L);
    System.out.println("受影响的行数为:"+i+"行");
}
//根据条件删除
@Test
public void deleteByMap(){
    HashMap<String, Object> map = new HashMap<>();
    //删除数据库中name为小红、sex为女的数据
    map.put("name","小红");
    map.put("sex","女");
    int i = userMapper.deleteByMap(map);
    System.out.println("受影响的行数为:"+i+"行");
}

图:

 3.更新操作

使用updateXXX方法来实现数据的修改。

示例:

//更新操作
@Test
public void update(){
    User user = new User();
    //将id为2的用户性别改为女
    user.setId(2L);
    user.setSex('女');
    int i = userMapper.updateById(user);
    System.out.println("受影响的行数为:"+i+"行");
}

图:

五.条件构造器

1.概述

我们在实际操作数据库的时候会涉及到很多的条件。所以MybatisPlus为我们提供了一个功能强大 的条件构造器Wrapper。使用它可以让我们非常方便的构造条件。

其继承体系如下:

在其子类AbstractWrapper中提供了很多用于构造Where条件的方法。

AbstractWrapper的子类QueryWrapper则额外提供了用于针对Select语法的select方法。可以用来设查询哪些列。

AbstractWrapper的子类UpdateWrapper则额外提供了用于针对SET语法的set方法。可以用来设对哪些列进行更新。

完整的AbstractWrapper方法可以参照:条件构造器 | MyBatis-Plus

准备的表如下:

2.常用AbstractWrapper方法:

示例一

SQL语句如下:

SELECT 
    id,name,sex,phone 
FROM 
    tb_user 
WHERE 
    id > 4 AND phone = '190'

 如果用Wrapper写法如下:

@Test
public void testWrapper01(){
    QueryWrapper wrapper = new QueryWrapper<>();
    wrapper.gt("id",4L);
    wrapper.eq("phone","190");
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

示例二

SQL语句如下:

SELECT 
   id,name,sex,phone 
FROM 
   tb_user 
WHERE 
   id IN (4,5,6,7,8,9) AND 
   id BETWEEN 6 AND 9 AND 
   name LIKE '%武%'

如果用Wrapper写法如下:

@Test
public void testWrapper02(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.in("id",4,5,6,7,8,9);
    wrapper.between("id",6,9);
    wrapper.like("name","武");
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

示例三

SQL语句如下:

SELECT 
  id,name,sex,phone 
FROM 
  tb_user 
WHERE 
  id IN (4,5,6,7,8,9) AND 
  id > 5 
ORDER BY 
  phone DESC

如果用Wrapper写法如下:

@Test
public void testWrapper03(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.in("id",4,5,6,7,8,9);
    wrapper.gt("id",5);
    wrapper.orderByDesc("phone");
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

3.常用QueryWrapper方法

QueryWrapper的select可以设置要查询的列

示例一

SQL语句如下

SELECT 
  id,name 
FROM 
  tb_user

MybatisPlus写法如下

@Test
public void testSelect01(){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("id","name");
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}

示例二(示例一的变种)

SQL语句如下

SELECT 
  id,name 
FROM 
  tb_user

MybatisPlus写法如下

select方法的第一个参数为实体类的字节码对象,第二个参数为Predicate类型,可以使用lambda的写法,过滤要查询的字段(主键除外)

@Test
public void testSelect02(){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select(User.class, new Predicate<TableFieldInfo>() {
        @Override
        public boolean test(TableFieldInfo tableFieldInfo) {
            return "name".equals(tableFieldInfo.getColumn());
        }
    });
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}

问题:那如果SQL是"SELECT id,name,phone FROM tb_user"这样的怎么写呢?

示例三

SQL语句如下:

SELECT 
  id,name,phone 
FROM 
  tb_user

MybatisPlus写法如下(未按照视频代码实现)

select方法参数研究???

@Test
public void testSelect03(){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select(User.class,new Predicate<TableFieldInfo>() {
        @Override
        public boolean test(TableFieldInfo tableFieldInfo) {
            return !"sex".equals(tableFieldInfo.getColumn());
        }
    });
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}

4.常用UpdateWrapper方法

我们前面在使用update方法时需要创建一个实体类对象传入,用来指定要更新的列及对应的值。但是如果需要更新的列比较少时,创建这么一个对象显的有点麻烦和复杂。我们可以使用UpdateWrapper的set方法来设置要更新的列及其值。同时这种方式也可以使用Wrapper去指定更复杂的更新条件。

示例

SQL语句如下

UPDATE tb_user SET phone = 777 WHERE id = 5

MybatisPlus写法如下

@Test
public void test(){
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.lt("id",4);
    updateWrapper.set("phone",111);
    userMapper.update(null,updateWrapper);
}

5.Lambda条件构造器

我们前面在使用条件构造器时列名都是用字符串的形式去指定。这种方式无法在编译期确定列名的合法性。所以MP提供了一个Lambda条件构造器可以让我们直接以实体类的方法引用的形式来指定列名。这样就可以弥补上述缺陷。

示例

SQL语句如下

SELECT * FROM tb_user WHERE phone > 180 AND sex = '女'

之前的写法如下

@Test
public void testWrapper01(){
    QueryWrapper wrapper = new QueryWrapper<>();
    wrapper.gt("phone",180);
    wrapper.eq("sex","女");
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

如果使用Lambda条件构造器写法如下

@Test
public void testLambdaQuery(){
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.gt(User::getPeoplephone,180);
    queryWrapper.eq(User::getSex,"女");
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}

六.自定义SQL

虽然MybatisPlus为我们提供了很多常用的方法,并且也提供了条件构造器。但是如果真的遇到了复杂的SQL时,我们还是需要自己去定义方法,自己去写对应的SQL,这样SQL也更有利于后期维护。因为MybatisPlus是对mybatis做了增强,所以还是支持之前Mybatis的方式去自定义方法。同时也支持在使用Mybatis的自定义方法时使用MP的条件构造器帮助我们进行条件构造。接下去我们分别来讲讲。

1.准备表和实体类

表结构

实体类

package cn.zcj.domain;
​
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
​
@Data
@ToString
@TableName("t_user")
public class People {
    private Double id;
    @TableField("create_time")
    private Double createTime;
    @TableField("update_time")
    private Double updateTime;
    @TableField("third_uid")
    private String thirdUid;
    private String phone;
    private String email;
    @TableField("nick_name")
    private String nickName;
    @TableField("bit_state")
    private Double bitState;
    @TableField("sec_level")
    private Integer secLevel;
    @TableField("login_id")
    private Double loginId;
}

2.2种方式

2.1.Mybatis方式

第一步:定义方法

在Mapper接口中定义方法

第二步:创建XML文件

先配置xml文件存放的目录

mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml

再创建对应的xml映射文件

第三步:Mapper层编写接口

@Component
public interface PeopleMapper extends BaseMapper<People> {
    People selectByPeopleId(Long id);
​
    List<People> selectPeopleByWrapper(@Param(Constants.WRAPPER)  QueryWrapper<People> wrapper);
}

第四步:在XML映射文件中编写SQL

创建对应的标签,编写对应的SQL语句

<?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="cn.zcj.mapper.PeopleMapper">
    <select id="selectByPeopleId" resultType="cn.zcj.domain.People">
        SELECT * FROM `t_user` where id = #{id}
    </select>
</mapper>

第五步:测试

@Test
public void test01(){
    People people = peopleMapper.selectByPeopleId(5L);
    System.out.println(people);
}

2.2.Mybatis方式结合条件构造器

我们在使用上述自定义方法时。如果希望自定义方法能够像MybatisPlus自带方法一样使用条件构造器来进行条件构造的话只需要使用如下方式即可:

第一步:方法定义中添加Wrapper类型参数

添加Wrapper类型的参数,并且要注意给其指定参数名。

@Component
public interface PeopleMapper extends BaseMapper<People> {
    List<People> selectPeopleByWrapper(@Param(Constants.WRAPPER)  QueryWrapper<People> wrapper);
}

第二步:在SQL语句中获取Wrapper拼接的SQL片段进行拼接

<select id="selectPeopleByWrapper" resultType="cn.zcj.domain.People">
    SELECT * FROM `t_user` ${ew.customSqlSegment}
</select>

【注意】不能使用#{},应该用${}

第三步:测试

package cn.zcj;
​
import cn.zcj.domain.People;
import cn.zcj.mapper.PeopleMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
​
import java.util.List;
​
@SpringBootTest
@RunWith(SpringRunner.class)
public class twoTest {
    @Autowired
    private PeopleMapper peopleMapper;
​
    @Test
    public void test02(){
        QueryWrapper<People> wrapper = new QueryWrapper<>();
        wrapper.in("id",1,2,3,7,8);
        wrapper.between("login_id",16,20);
        wrapper.like("third_uid","魅");
        List<People> people = peopleMapper.selectPeopleByWrapper(wrapper);
        System.out.println(people);
    }
}

七.分页查询

1.基本分页查询

1.1配置分页查询拦截器

package cn.zcj.config;
​
import com.baomidou.mybatisplus.annotation.DbType;
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 {
    //分页查询拦截器
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }
}

1.2.进行分页查询

@Test
public void pageList(){
    Page<People> page = new Page<>();
    //每页展示数据条数
    page.setSize(2);
    //查询第几页
    page.setCurrent(1);
    peopleMapper.selectPage(page, null);
    //获取当前页的数据
    System.out.println(page.getRecords());
    //获取记录总数
    System.out.println(page.getTotal());
    //当前页码
    System.out.println(page.getCurrent());
}

2.多表分页查询

如果需要在多表查询时进行分页查询的话,就可以在mapper接口中自定义方法,然后让方法接收Page对象

示例

1.需求

查询商品表中拥有同一种商品的所有用户(需要将商品表和用户表进行联表查询)

2.准备工作

表准备:

domain实体类的准备:

3.接口定义

@Component
public interface GoodsMapper extends BaseMapper<Goods> {
    IPage<Goods> selectUserWithGoods(Page<Goods> page);
}

4.Xml文件Sql语句准备

<?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="cn.zcj.mapper.GoodsMapper">
    <select id="selectUserWithGoods" resultType="cn.zcj.domain.Goods">
        SELECT t2.name,t1.* FROM tb_user t2,t_goods t1 WHERE t1.id = t2.tId
    </select>
</mapper>

5.测试

@Test
public void testSelectUserWithGoods(){
    Page<Goods> page = new Page<>();
    //每页展示数据条数
    page.setSize(2);
    //查询第几页
    page.setCurrent(1);
    goodsMapper.selectUserWithGoods(page);
    //获取当前页的数据
    System.out.println(page.getRecords());
    //获取记录总数
    System.out.println(page.getTotal());
    //当前页码
    System.out.println(page.getCurrent());
}

八.service层接口(缺)

​ MybatisPlus为我们提供了Service层的实现,我们只需要编写一个接口,继承IService,并创建一个接口接口的实现类,让这个实现类去继承ServiceImpl,即可使用。

​ 相比于Mapper接口,Service层主要是支持了更多批量操作的方法。

1.基本使用

2.自定义方法

九.代码生成器

高级

一.自动填充

在实际项目中的表和Goods表一样,有更新时间、创建时间、创建者、更新者等字段。

我们可以使用@TableField的fill属性来设置字段的自动填充。让我们能更为方便的更新相关字段。

示例

1.在对应字段上增加注解

使用@TableField注解的fill属性来标注哪些字段需要在自动填充,加了注解MybatisPlus才会在对应的SQL中为我们预留字段。而属性值代表我们在什么进行什么操作时需要预留的字段。

 实体类完整代码:

@Data
@ToString
@TableName("t_goods")
public class Goods {
    private double id;
    //创建时间
    @TableField(value = "create_time",fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    //更改时间
    @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @TableField("third_uid")
    private String thirdUid;
    private String phone;
    private String email;
    @TableField("nick_name")
    private String nickName;
    @TableField("bit_state")
    private Double bitState;
    @TableField("sec_level")
    private Integer secLevel;
    @TableField("login_id")
    private Double loginId;
    //逻辑删除专用字段
    @TableField("delete_flag")
    private Integer deleteFlag;
}

 2.自定义填充处理器MetaObjectHandler

package cn.zcj.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class MyMetaObjectHanfler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", LocalDateTime.now(),metaObject);
        this.setFieldValByName("updateTime", LocalDateTime.now(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", LocalDateTime.now(),metaObject);
    }
}

3. 测试

@Test
public void testFill(){
    Goods goods = new Goods();
    goods.setId(35L);
    goods.setEmail("123456789");
    goods.setLoginId(new Double(8899L));
    //goodsMapper.insert(goods);
    goodsMapper.updateById(goods);
}

二.逻辑删除

MybatisPlus支持逻辑删除。只需要将配置好的逻辑删除的实体字段名,代表删除的字段值、代表未删除的字段值后即可。

【注意】如果是MybatisPlus的3.3.0版本之前则需要在对应的字段上加@TableLogic注解

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///ymcc-user?serverTimezone=UTC
    username: root
    password: 123456
mybatis-plus:
  configuration:
    #日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #是否开启自动驼峰命名规则
    map-underscore-to-camel-case: false
  global-config:
    db-config:
      #逻辑删除的实体字段名
      logic-delete-field: deleteFlag
      #代表删除的字段值
      logic-delete-value: 0
      #代表未删除的字段值
      logic-not-delete-value: 1
      #id生成策略:auto为数据库自增
      id-type: auto
      table-prefix: tb_
  mapper-locations: classpath*:/mapper/**/*.xml

关系图:

测试

@Test
public void testDelete(){
    goodsMapper.deleteById(1L);
}

测试结果

三.乐观锁

1.乐观锁使用

​ 并发操作时,我们需要保证对数据的操作不发生冲突。乐观锁就是其中一种方式。 乐观锁就是先加上不存在并发冲突问题,在进行实际数据操作的时候再检查是否冲突。 我们在使用乐观锁时一般在表中增加一个version列。 用来记录我们对每天记录操作的版本。每次对某条记录进行过操作是,对应的版本也需要+1。

​ 然后我们在每次要进行更新操作时,先查询对应数据的version值。在执行更新时,"set version =老版本+1where version =老版本",如果在查询老版本号到更新操作的中间时刻有其他人更新了这条数据,这样这次更新语句就会更新失败.

     这里在更新时对version的操作如果有我们自己做就会显的有点麻烦。所以MP提供了乐观锁插件。

​     使用后我们就可以非常方便的实现对version的操作。

1.数据库添加version字段、实体类添加字段并使用@Version注解

【注意】在更新之前我们一定要先查询到version设置到实体类上再更新才能生效

2.配置对应插件

package cn.zcj.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.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {
    //分页插件
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }

    //旧版乐观锁插件
    @Bean
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptorOld(){
        return new OptimisticLockerInnerInterceptor();
    }
    //新版乐观锁插件
    @Bean
    public MybatisPlusInterceptor optimisticLockerInnerInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

 3.对更新功能进行测试

@Test
public void testFill(){
    Goods goods = new Goods();
    goods.setId(35L);
    goods.setEmail("1234");
    //假设查到的version为1
    goods.setVersion(1);
    goods.setLoginId(new Double(100L));
    goodsMapper.updateById(goods);
}

 测试结果

2.多插件配置问题

​ 在使用MybatisPlus的3.4.0以后的版本时,如果遇到多个插件的情况,在配置的时候只需要注入一个MybatisPlusInterceptor对象,把插件对象添加到MybatisPlusInterceptor对象中即可。

【注意】插件与插件之前存在互相依赖关系,此处的分页插件必须在乐观锁插件之前添加到MybatisPlusInterceptor对象中,否则容易出现乐观锁失效的情况

合并前(分开写法):

合并后(合并写法):

附录:项目结构图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值