MyBatisPlus 学习笔记_MP的AR模式

  • 狂神说 MyBatisPlus 学习笔记

    一、快速入门

    文档:https://mp.baomidou.com/

    使用第三方组件:

    1. 导入对应依赖
    2. 研究依赖如何配置
    3. 代码如何编写
    4. 提高扩展技术能力

    步骤:

    1、创建数据库 mybatis_plus


    2、创建user表

    DROP TABLE IF EXISTS user;
    
    CREATE TABLE user
    (
    	id BIGINT(20) NOT NULL COMMENT '主键ID',
    	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    	PRIMARY KEY (id)
    );
    

    2.1、插入数据

    INSERT INTO user (id, name, age, email) VALUES
    (1, 'Jone', 18, '[email protected]'),
    (2, 'Jack', 20, '[email protected]'),
    (3, 'Tom', 28, '[email protected]'),
    (4, 'Sandy', 21, '[email protected]'),
    (5, 'Billie', 24, '[email protected]');  
    

    3、创建项目


    4、导入依赖

    <!--数据库驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.20</version>
    </dependency>
    <!--mybatis-plus-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.0.5</version>
    </dependency>
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    

    说明:我们使用mybatis-plus可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus!

    5、连接数据库,这一步和mybatis相同

    # mysql
    spring.datasource.username=root
    spring.datasource.password=root
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    

    6、传统方式:pojo-dao(连接mybatis,配置mapper.xml文件)- service - controller

    6、使用了mybatis-plus 之后

img
pojo(实体类)

  • extends Model : 必须存在对应的原始mapper并继承baseMapper并且可以使用的前提下才能使用此 AR 模式 !!!

文章末尾有关于AR模式的简单介绍

@Data
@TableName("user")
public class User extends Model<User> {
    
    
    @TableId
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private Long managerId;
    private LocalDateTime createTime;
}

mapper接口(dao层):

// 在对应的Mapper上面继承基本的接口 BaseMapper
@Repository // 代表持久层
public interface UserMapper extends BaseMapper<User> {
    
    
    // 所有的CRUD操作都已经基本完成了
    // 你不需要像以前的配置一大堆文件了
}

Service层:

import com.baomidou.mybatisplus.extension.service.IService;
import com.zhixi.pojo.User;

public interface UserService extends IService<User> {
    
    
}

Service层实现类:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    
    

}

启动类:

  • 注意点:我们需要在主启动类上去扫描我们的mapper包下的所有接口

img

测试类中测试

@SpringBootTest
class MybatisPlusApplicationTests {
    
    

    // 继承了BaseMapper,所有的方法都来自父类
    // 我们也可以编写自己的扩展方法
    @Autowired
    UserMapper userMapper;

    @Test
    void contextLoads() {
    
    
        // 参数是一个 Wrapper , 条件构造器,这里我们先不用 null
        // 查询全部用户
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

思考问题:

1、SQL是谁帮我们写的?MyBatis-Plus都写好了

2、方法哪里来的?MyBatis-Plus 都写好了

二、配置日志

我们所有的sqld现在都是不可见的,我们希望知道它是怎么执行的,所以我们必须要看日志!

# 配置日志 (系统自带的,控制台输出)
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

配置完毕日志之后,后面的学习就需要注意这个自动生成的SQL,你们就会喜欢上MyBatis-Plus !

三、CRUD

1. 插入操作

Insert 插入

@Test
public void testInsert() {
    
    
    User user = new User();
    user.setName("Dainel");
    user.setAge(3);
    user.setEmail("[email protected]");

    int result = userMapper.insert(user);// 帮我们自动生成id
    System.out.println(result);// 受影响的行数
    System.out.println(user);// 发现: id自动回填
}

数据库插入的id默认值为:全局的唯一id

2. 主键生成策略

默认 ID_WORKER 全局唯一id

分布式系统唯一id生成:https://www.cnblogs.com/haoxinyue/p/5208136.html

雪花算法:

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!

主键自增

我们需要配置主键自增:

  1. 实体类字段上 @TableId(type = IdType.AUTO)

  2. 数据库字段上一定是自增的

    img

  3. 再次测试即可

其余的源码解释

public enum IdType {
    
    
    AUTO(0), // 数据库id自增
    NONE(1), // 未设置主键
    INPUT(2), // 手动输入,自己写id
    ID_WORKER(3), // 默认的全局唯一id
    UUID(4), // 全局唯一id uuid
    ID_WORKER_STR(5); // ID_WORKER 字符串表示法
}

3、更新操作

@Test
    /*更新操作*/
void updateUser() {
    
    
    // 查询到要更新的用户
    User user = userMapper.selectById(7);
    // 要更新的值
    user.setName("demo");
    user.setAge(21);
    // 执行更新
    userMapper.updateById(user);
}

4. 自动填充

创建时间、修改时间!这些个操作一般都是自动化完成的,我们不希望手动更新!

阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上!而且需要自动化!

方式一:数据库级别(工作中不允许修改数据库)

  1. 在表中新增字段 create_time,update_time;注意将更新的时间戳勾选

    img

  2. 再次测试插入方法,我们需要先把实体类同步

    private Date createTime;
    private Date updateTime;
    
  3. 再次查看更新结果即可

img

方式二:代码级别

  1. 删除数据库中的默认值、更新操作

  2. 实体类的字段属性上需要增加注解

    //字段添加填充内容
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    
  3. 编写处理器来处理这个注解即可:handler/MyMetaObjectHandler

    package com.kuang.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 // 一定不要忘记把处理器加到IOC容器中
    public class MyMetaObjectHandler implements MetaObjectHandler {
          
          
    
        // 插入时候的填充策略
        @Override
        public void insertFill(MetaObject metaObject) {
          
          
            log.info("start insert fill ...");
            // setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
            this.setFieldValByName("createTime", new Date(), metaObject);
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
    
        // 更新时的填充策略
        @Override
        public void updateFill(MetaObject metaObject) {
          
          
            log.info("start update fill ...");
            this.setFieldValByName("updateTime", new Date(), metaObject);
        }
    
    }
    
  4. 测试插入

  5. 测试更新,观察时间已经更新

img

5. 乐观锁

在面试过程中,我们经常会被问到乐观锁,悲观锁。

乐观锁:顾名思义,它总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值测试!

悲观锁:顾名思义,它总是认为总是出现问题,无论干什么都上锁!再去操作!

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

测试一下MyBatisPlus的插件:

1、数据库中增加一个version字段,并设置默认值为1

2、实体类添加注解

@Version // 乐观锁的version注解
private Integer version;

3、编写配置

config/MybatisPlusConfig

// 配置,会被spring扫描到
@Configuration
public class MybatisPlusConfig {
    
    
    // 注册乐观锁
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInnerInterceptor(){
    
    
        return new OptimisticLockerInterceptor();
    }
}

4、测试方法

测试乐观锁成功:

将2号的姓名改为lipu。看他的version会怎么变化

@Test
void OptimisticLock() {
    
    
    // 查询到要进行更新的用户
    User user = userMapper.selectById(2);
    // 修改用户的属性
    user.setName("lipu");
    user.setAge(28);
    // 提交更新
    userMapper.updateById(user);
}

img

测试乐观锁失败(多线程下)

// 测试乐观锁失败!多线程下
@Test
public void testVersionFall() {
    
    
    // 线程1
    User user1 = userMapper.selectById(9);
    user1.setName("fan111");
    user1.setAge(14);
    // 线程2
    User user2 = userMapper.selectById(9);
    user2.setName("fan222");
    user2.setAge(24);
    userMapper.updateById(user2);
    //自旋锁来多次尝试提交!
    userMapper.updateById(user1); //如果没有乐观锁就会覆盖插队线程的值
}

img

6. 查询操作

// 测试查询
@Test
public void testSelectById(){
    
    
    User user = userMapper.selectById(1);
    System.out.println(user);
}

// 批量查询
@Test
public void testSelectByBatchIds(){
    
    
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    users.forEach(System.out::println);
}

// 按照条件查询之一使用 map
@Test
public void testSelectByMap(){
    
    
    HashMap<String, Object> map = new HashMap<>();
    // 自定义要查询
    map.put("name","Dainel");
    map.put("age","6");
    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

7、分页查询

分页网站频繁使用

  1. 原始使用limit进行分页
  2. pageHelper第三方插件
  3. MybatisPlus内置了分页插件

如何使用:

1、配置分页拦截器:config/MybatisPlusConfig

  // 分页插件
  @Bean
  public PaginationInterceptor paginationInterceptor() {
    
    
      return new PaginationInterceptor();
  }

2、编写查询

 // 分页查询
 @Test
 void selectLimit() {
    
    
     Page<User> page = new Page<User>(2, 5);
     // 获取通过分页查询到的记录条数
     page.getRecords().forEach(System.out::println);
     // 查询
     userMapper.selectPage(page, null);
     // 查询总记录条数
     System.out.println("总计数条数:" + page.getTotal());
 }

img

8. 删除操作

// 测试删除
@Test
public void testdelete(){
    
    
    userMapper.deleteById(6L);
}

// 测试批量删除
@Test
public void testdeleteBatchId(){
    
    
    userMapper.deleteBatchIds(Arrays.asList(1,14));
}

//通过map删除
@Test
public void testDeleteByMap(){
    
    
    HashMap<String, Object> map = new HashMap<>();
    map.put("name","KUANG");
    userMapper.deleteByMap(map);
}

我们在工作中会遇到一些问题:逻辑删除!

9. 逻辑删除

物理删除:从数据库中直接移除

逻辑删除:在数据库中没有被移除,而是通过一个变量让他生效!deleted=0 --> deleted=1

管理员可以查看被删除的记录!防止数据的丢失!类似于回收站!

步骤:

1、在数据库表中增加一个deleted字段

img

2、修改实体类

// 表逻辑删除
@TableLogic
private int deleted;

3、配置:config/MybatisPlusConfig

注意:在新版本的MP中,不需要再写逻辑删除配置了,知道就行,只需要在实体类逻辑删除字段上加上注解即可!

// 逻辑删除组件
public ISqlInjector sqlInjector(){
    
    
    return new LogicSqlInjector();
}

4、properties配置(默认,可以不配置)

# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

测试逻辑删除:

 // 逻辑删除
 @Test
 void deleteLogic() {
    
    
     userMapper.deleteById(1);
 }

img

逻辑删除成功、

img

我们通过查询1号用户,验证下看是否能够查询的到:

img

四、性能分析插件

PerformanceInterceptor在3.2.0被移除了,如果想进行性能分析,用第三方的,官方这样写的“该插件 3.2.0 以上版本移除推荐使用第三方扩展 执行 SQL 分析打印 功能

https://baomidou.com/guide/p6spy.html

我们在平时的开发中,会遇到一些慢sql。解决方案:测试,druid监控…

作用:性能分析拦截器,用于输出每条SQL语句及其执行时间

MyBatisPlus也提供性能分析插件,如果超过这个时间就停止运行!

1、导入插件

// SQL执行效率插件
@Bean
@Profile({
    
    "dev","test"})
public PerformanceInterceptor performanceInterceptor(){
    
    
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    performanceInterceptor.setMaxTime(100); //ms 设置sql执行的最大时间,如果超过了则不执行
    performanceInterceptor.setFormat(true); // 是否格式化
    return performanceInterceptor;
}

记住,要在SpringBoot中配置环境为dev或者test环境!

# 开发环境
spring.profiles.active=dev

2、测试使用

 // 分页查询
 @Test
 void selectLimit() {
    
    
     Page<User> page = new Page<User>(1, 5);
     // 获取通过分页查询到的记录条数
     page.getRecords().forEach(System.out::println);
     // 查询
     userMapper.selectPage(page, null);
     // 查询总记录条数
     System.out.println("总计数条数:" + page.getTotal());
 }

img

只要超出时间就会抛出异常

使用性能分析插件可以提高效率,新版本MP已经移除该拆件了,可以使用druid

五、代码自动生成**非常NB

dao、pojo、service、controller都给我自己去编写完成!

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、

Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

只需要改实体类名字 和包名 还有 数据库配置即可

需要使用到的pom依赖:

 <dependencies>
        <!--swagger依赖-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>

        <!-- 模板引擎 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>
        <!--导入mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </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>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

测试代码:/test/…

package com.zhixi;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
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.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;

// 代码自动生成器
public class zhixiCode {
    
    
    public static void main(String[] args) {
    
    
        // 需要构建一个 代码自动生成器 对象
        AutoGenerator mpg = new AutoGenerator();

        // 配置策略
        // 1、全局配置
        GlobalConfig gc = new GlobalConfig();
        // 代码输出到哪个目录(获取到项目目录)
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        // 设置作者
        gc.setAuthor("张志喜");
        // 是否打开资源管理器(生成完代码打开目录)
        gc.setOpen(false);
        // 是否覆盖原来的文件
        gc.setFileOverride(false);

        // 去掉IService的I前缀(正则)
        gc.setServiceName("%sService");

        // 设置字段
        gc.setIdType(IdType.ID_WORKER);
        gc.setDateType(DateType.ONLY_DATE);
        // 配置swagger
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);

        //2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://182.92.209.212:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("密码");
        // 数据库类型
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        //3、包的配置(只需要改实体类名字 和包名 还有 数据库配置即可)
        PackageConfig pc = new PackageConfig();

        // 模块名
        pc.setModuleName("blog");
        // 设置类放在哪个包下
        pc.setParent("com.kuang");
        // 设置实体类
        pc.setEntity("entity");
        // 设置mapper
        pc.setMapper("mapper");
        // 设置services层
        pc.setService("service");
        // 设置controller层
        pc.setController("controller");

        mpg.setPackageInfo(pc);

        //4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        // 设置要映射的表名
        strategy.setInclude("blog_tags", "course", "links", "sys_settings", "user_record", " user_say");

        // 设置下划线转驼峰命名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        // 自动lombok;
        strategy.setEntityLombokModel(true);
        // 设置逻辑删除列名
        strategy.setLogicDeleteFieldName("deleted");

        // 自动填充配置
        TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);/*创建时间*/
        TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);/*修改时间*/
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        // 添加自动填充
        strategy.setTableFillList(tableFills);

        // 乐观锁
        strategy.setVersionFieldName("version");/*设置版本字段名称*/
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);// localhost:8080/hello_id_2

        mpg.setStrategy(strategy);

        mpg.execute(); //执行
    }
}

img

六、SQL注入器:实现自定义通用方法

MP在一开始就给大家提供了很多通用的方法,在DefaultSqlInjector这个类中,在MethodList这个集合当中包含的都是通用方法类,如果想要使用自定义通用方法,也需要添加到这个集合当中。

/**
 * SQL 默认注入器
 */
public class DefaultSqlInjector extends AbstractSqlInjector {
    
    

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
    
    
        return Stream.of(
            new Insert(),
            new Delete(),
            new DeleteByMap(),
            new DeleteById(),
            new DeleteBatchByIds(),
            new Update(),
            new UpdateById(),
            new SelectById(),
            new SelectBatchByIds(),
            new SelectByMap(),
            new SelectOne(),
            new SelectCount(),
            new SelectMaps(),
            new SelectMapsPage(),
            new SelectObjs(),
            new SelectList(),
            new SelectPage()
        ).collect(toList());
    }
}

第一步:创建自定义方法的类(以创建删除所有记录的方法为例)

类名是DelFillUserMethod,这个是自定义的,但是最好是见名知意的类名。
继承AbstractMethod抽象类,AbstractMethod是抽象的注入方法类,每个通用方法也都继承了这个类,也是为了方便调用里面的方法
重写injectMappedStatement方法,injectMappedStatement内是我们完成我们这个方法具体的逻辑。

package com.zhixi.method;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

/**
* @author zhangzhixi
* @date 2021-6-13 20:56
*/
public class DelAllMethod extends AbstractMethod {
    
    
   @Override
   public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
    
    
       // 1、自定义执行的sql语句
       String sql = "delete from " + tableInfo.getTableName();
       // 2、mapper接口方法名
       String method = "deleteUserAll";
       /**
        * 3、添加动态SQL标签处理器
        * 注意只需要传入sql即可
        */
       SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
       // 4、返回statement对象
       return addDeleteMappedStatement(mapperClass, method, sqlSource);
   }
}

第二步:创建注入器,并把自定义的方法添加到集合当中

  • 类名是CustomSqlInjector,自定义的
  • 继承DefaultSqlInjector并重写getMethodList,SQL 默认注入器上面也有提到过,我们得把我们自定义的方法加入到通用方法的集合methodList当中
 package com.zhixi.injector;
 
 import com.baomidou.mybatisplus.core.injector.AbstractMethod;
 import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
 import com.zhixi.method.DelAllMethod;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
 
 @Component
 public class MyInjector extends DefaultSqlInjector {
    
    
     @Override
     public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
    
    
         // 1、先要通过父类方法,获取到原有的集合,不然会自带的通用方法会失效的
         List<AbstractMethod> methodList = super.getMethodList(mapperClass);
         // 2、添加自定义mapper类
         methodList.add(new DelAllMethod());
         return methodList;
     }
 }

第三步:在Mapper中添加自定义的方法

package com.zhixi.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhixi.pojo.User;
import org.springframework.stereotype.Repository;

@Repository
public interface UserMapper extends BaseMapper<User> {
    
    
    /**
     * 删除所有记录
     *
     * @return 影响行数
     */
    int deleteUserAll();
}

什么是AR模式:简单来说就是通过实体类对象,直接进行表的增删改查操作。

实现AR模式在MP中有两个基本要求:

  1. 实体类继承Model类
//如果不加下面第二个注解,会报一个警告(自动调用equals和hashcode方法,没有调用父类的)
@Data
@EqualsAndHashCode(callSuper = false)
public class User extends Model<User> {
    
    
  ...
}
  1. 必须存在原始的Mapper接口并继承BaseMapper
public interface UserMapper extends BaseMapper<User> {
    
    
   ...
}

实战演练:

package com.mp.first;

import com.mp.first.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ARTest {
    
    

    /**
     * 这里就不用再注入userMapper了,直接操作实体类就好
     */

    @Test
    public void insert(){
    
    
        User user = new User();
        user.setName("老刘");
        user.setAge(18);
        user.setEmail("[email protected]");

        boolean insert = user.insert();
        System.out.println("插入是否成功:"+insert);
    }

    @Test
    public void selectById(){
    
    
        User user = new User();

        User userSelect = user.selectById(1321469479649107970L);
        System.out.println("查到了:"+userSelect);
    }

    @Test
    public void selectById2(){
    
    
        User user = new User();
        user.setId(1321469479649107970L);

        User userSelect = user.selectById();
        System.out.println("查到了:"+userSelect);
    }

    @Test
    public void updateById(){
    
    
        User user = new User();
        user.setId(1321469479649107970L);
        user.setName("老王");

        boolean userSelect = user.updateById();
        System.out.println(userSelect);
    }

    @Test
    public void deleteById(){
    
    
        User user = new User();
        user.setId(1321469479649107970L);

        boolean userSelect = user.deleteById();
        System.out.println(userSelect);
    }

//    SELECT id,name,age,email FROM user WHERE id=?
//    UPDATE user SET name=?, age=?, email=? WHERE id=?
    @Test
    public void insertOrUpdate(){
    
    
        User user = new User();
        //不传入id时,是做新增操作
        user.setName("老牛");
        user.setAge(58);
        user.setEmail("[email protected]");

        //传入id时,会先在数据库中找;如果没有此id,怎做新增操作,如果有此id则做修改操作
        user.setId(1321473206095212546L);

        boolean insert = user.insertOrUpdate();
        System.out.println(insert);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43842093/article/details/124974521