草庐IT

MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)

不吃紫菜 2023-04-19 原文

CRUD

官方文档:https://baomidou.com/
(建议多看看官方文档,每种功能里面都有讲解)【本文章使用的mybatisplus版本为3.5.2】

条件构造器

一般都是用service层的方法,因为比mapper层的全。十分重要:Wrapper 记住查看输出的SQL进行分析

相当于创建一个构造器对象,然后讲需要查询or更新的条件写在里面,最后打包给mapper or service层的插入、更新方法

下图是Wapper的子类,QueryWrapperUpdateWrapper是一般的Wrapper,AbstractLambdaWrapper 是lambda语法糖的链式操作(两者选择一种使用即可)

下图是wrapper的条件方法,就不一一介绍了,下面举了六个就基本例子

1、测试一

@Test
public void testWrapper1() {
    //参数是一个wrapper ,条件构造器,和刚才的map对比学习!
    //查询name不为空,email不为空,age大于18的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
        .isNotNull("name")
        .isNotNull("email")
        .ge("age",18);
    List<User> userList = userMapper.selectList(wrapper);
    userList.forEach(System.out::println);
}

测试二

@Test
public void testWrapper2() {
    //查询name=wsk的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name","wsk");
    //查询一个数据selectOne,若查询出多个会报错
    //Expected one result (or null) to be returned by selectOne(), but found: *
    //若出现多个结果使用list或map
    User user = userMapper.selectOne(wrapper);//查询一个数据,若出现多个结果使用list或map
    System.out.println(user);
}

测试三

@Test
public void testWrapper3() {
    //查询age在10-20之间的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.between("age", 10, 20);//区间
    Integer count = userMapper.selectCount(wrapper);//输出查询的数量selectCount
    System.out.println(count);
}

测试四

@Test
public void testWrapper4() {
    //模糊查询
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
        .notLike("name","s")
        .likeRight("email","qq");//qq%  左和右?
    List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
    maps.forEach(System.out::println);
}

测试五

@Test
public void testWrapper5() {
    //模糊查询
    // SELECT id,name,age,email,version,deleted,create_time,update_time 
    //FROM user 
    //WHERE deleted=0 AND id IN 
    //(select id from user where id<5)
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //id 在子查询中查出来
    wrapper.inSql("id","select id from user where id<5");
    List<Object> objects = userMapper.selectObjs(wrapper);
    objects.forEach(System.out::println);
}

测试六

@Test
public void testWrapper6() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //通过id进行降序排序
    wrapper.orderByDesc("id");
    List<User> userList = userMapper.selectList(wrapper);
    userList.forEach(System.out::println);
}

CRUD接口

基本配置:

0、创建数据库

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 '邮箱',
    version INT(10) NOT NULL DEFAULT 1 COMMIT '乐观锁版本号',
    DELETED INT(10) NOT NULL DEFAULT 0 COMMIT '逻辑删除',
    CREATE_TIME DATE COMMIT '创建时间',
    modify_time DATE COMMIT '更新时间',
    PRIMARY KEY (id)
);

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, '工藤新一','test1@baomidou.com'),
(2, '毛利兰','est2@baomidou.com'),
(3, '柯南', 28, 'test3@baomidou.com'),
(4, '灰原哀', 21, 'test4@baomidou.com'),
(5, '工藤有希子', 24, 'test5@baomidou.com');

1、创建项目,导入依赖

		<!--spring-boot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--SpringBootTest-->
        <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>
        </dependency>
        <!--mysql 驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

2、yaml

#设置开发环境
spring:
  datasource:
    username: root
    password: 123456
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    url: jdbc:p6spy:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useUnicode=true&characterEncoding=utf

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

3、创建实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user")
public class User {
    @TableId(type = IdType.AUTO)
    Long id;
    String name;
    int age;
    String email;
    @Version//乐观锁version注解
    private Integer version;
    private Integer isDelete;

    @TableField(fill = FieldFill.INSERT)
    private Date cTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date upTime;
}

4、写Mapper

@Repository
public interface UserMapper extends BaseMapper<User> {

}

5、写Service接口和实现类

//Service接口
public interface UserService extends IService<User> {	//别忘了继承这个父类

}

//实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {	//记得继承父类

}

6、之后就可以测试了

Mapper CRUD接口

顾名思义这个只有mapper层对象才有的方法

Insert

写数据库的时候id设置了主键自增的话,插入的时候不需要加入id,因为MP会自动添加并且自增的。

注:数据库写了id自增的话,在实体类设置主键生成策略是没用的,因为数据库设置了自增,数据库优先级高于代码

@Test//测试插入
public void insertTest(){
    User user = new User();
    user.setName("wsk");
    user.setAge(18);
    user.setEmail("2803708553@qq.com");
    Integer result = userMapper.insert(user); //会帮我们自动生成id
    System.out.println(result); //受影响的行数
    System.out.println(user); //通过日志发现id会自动回填(id是由雪花算法生成的,在主键生成策略部分有讲到)
}

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

Update

@Test//测试更新
public void updateTest(){
    User user = new User();
    user.setId(2L);//怎么改id??
    //通过条件自动拼接动态Sql
    user.setName("root");
    user.setAge(12);
    user.setEmail("root@qq.com");
    int i = userMapper.updateById(user);//updateById,但是参数是个user
    System.out.println(i);
}

Select

  • 通过id查询单个用户
@Test//通过id查询单个用户
public void testSelectById(){
    User user = userMapper.selectById(1L);
    System.out.println(user);
}

  • 通过id查询多个用户
@Test//通过id查询多个用户
public void testSelectBatchIds(){
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));
    users.forEach(System.out::println);
    //System.out.println(users);
}

  • 条件查询 通过map封装
@Test//通过条件查询之一  map(这里的map,相当于where后面的 name="conan"等条件)
public void testMap(){
    HashMap<String, Object> map = new HashMap<>();
    //自定义要查询的
    map.put("name","www");	//查询名字是www的数据
    map.put("name","111");	//查询名字是111的数据	最后的结果是取两者交集
    map.put("age",18);
    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

Delete

基本的删除任务:

@Test
public void testDeleteById(){
    userMapper.deleteById(1359507762519068681L);
}
@Test
public void testDeleteBatchIds(){
  userMapper.deleteBatchIds(Arrays.asList(1359507762519068675L,1359507762519068676L));
}
@Test
public void testD(){
    HashMap<String, Object> map = new HashMap<>();
    map.put("age","18");
    map.put("name","lol");
    userMapper.deleteByMap(map);
}

Service CRUD接口

顾名思义这是Service层才有的方法

Save

为了区分mapper层和service层的方法,所以service层的插入方法取名为save

@Test
void test(){
    User user = new User();
    user.setName("Conan");
    user.setAge(18);
    user.setEmail("毛利侦探事务所");
    //插入单条数据
    userService.save(user);
    // 插入(批量)
    userService.saveBatch(Arrays.asList(user));
}

Remove

service层删除方法取名为remove

 @Test
    void test(){
        User user = new User();
        user.setName("Conan");
        user.setAge(18);
        user.setEmail("毛利侦探事务所");

        HashMap<String,Object> map = new HashMap<>();
        map.put("name","Conan");

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","毛利小五郎");

        userService.remove(wrapper);    //根据条件构造器删除数据
        userService.removeById(16L);    //根据id删除数据,也可以根据实体类对象删除数据
        userService.removeByMap(map);   //根据map的条件删除记录
        userService.removeBatchByIds(Arrays.asList(user));  //批量删除 
    }

Update

@Test
    void test(){
        User user = new User();
        user.setName("Conan");
        user.setAge(18);
        user.setEmail("毛利侦探事务所");

        HashMap<String,Object> map = new HashMap<>();
        map.put("name","Conan");

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","毛利小五郎")
                .ge("age",18);


        userService.update(wrapper);    //根据条件构造器更新
        userService.updateById(user);   //根据传入的实体类id确定需要更新的数据,更新为传入的实体类对象
        userService.updateBatchById(Arrays.asList(user));   //批量更新
    }

Get

该方法只能查询一条数据,所以不推荐。查询用list方法

@Test
    void test(){
        User user = new User();
        user.setName("Conan");
        user.setAge(18);
        user.setEmail("毛利侦探事务所");

        HashMap<String,Object> map = new HashMap<>();
        map.put("name","Conan");

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","毛利小五郎")
                .ge("age",18);


        userService.getById(12L);   //根据id查询一条数据
        userService.getMap(wrapper);    //根据构造器查询一条数据,返回Mapper集合
    }

List

查询多条数据

@Test
void test(){
    User user = new User();
    user.setName("Conan");
    user.setAge(18);
    user.setEmail("毛利侦探事务所");

    HashMap<String,Object> map = new HashMap<>();
    map.put("name","Conan");

    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name","毛利小五郎")
        .ge("age",18);


    userService.list(); //查询全部数据
    userService.listMaps(); //查询全部数据,以map形式返回
    userService.listByMap(map); //根据map查询数据
    userService.listByIds(Arrays.asList(10L,15L));   //根据id查询数据
}

SaveOrUpdate

运行逻辑:直接更新,更新0行的话;就select,查询出来是0行;则就插入

有传入id的情况会优先更新,如果更新不了,则会插入新的数据

记得在实体类写上@TableId!!!

@Test
void test(){
    User user = new User();
    user.setName("Conan");
    user.setAge(18);
    user.setEmail("毛利侦探事务所");

    HashMap<String,Object> map = new HashMap<>();
    map.put("name","Conan");

    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.eq("name","毛利小五郎")
        .ge("age",18);


    userService.saveOrUpdate(user); //传入的对象id存在则更新,否则插入新数据
    userService.saveOrUpdate(user,wrapper); //根据更新条件构造器,更细数据
    userService.saveOrUpdateBatch(Arrays.asList(user)); //批量修改插入
}

Count

统计符合条件的数据的数量

@Test
    void test(){
        User user = new User();
        user.setName("Conan");
        user.setAge(18);
        user.setEmail("毛利侦探事务所");

        HashMap<String,Object> map = new HashMap<>();
        map.put("name","Conan");

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","毛利小五郎")
                .ge("age",18);
        
        userService.count();
        userService.count();
    }

Chain

链式调用,可以不用条件构造器完成 条件设置和增删改查。推荐!因为优雅!

Query
@Test
void test(){
    User user = new User();
    user.setName("Conan");
    user.setAge(18);
    user.setEmail("毛利侦探事务所");

    HashMap<String,Object> map = new HashMap<>();
    map.put("name","Conan");

    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name","毛利小五郎")
        .ge("age",18);

    List<User> userList = userService.query()
        .eq("name", "工藤新一")
        .gt("age", 17)
        .list();
    for(User  user01: userList) {
        System.out.println(user);
    }
}
Update
@Test
void test(){
    User user = new User();
    user.setName("Conan");
    user.setAge(18);
    user.setEmail("毛利侦探事务所");

    HashMap<String,Object> map = new HashMap<>();
    map.put("name","Conan");

    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name","毛利小五郎")
        .ge("age",18);

    userService.update()
        .eq("name", "工藤新一")
        .gt("age", 17)
        .update();
}

有关MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)的更多相关文章

  1. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  4. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  5. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  6. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  7. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  10. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

随机推荐