《springboot学习》 十九 springboot集成mybatis-plus

目录

前言

1.Mybatis plus简介

1.1特点:

1.2支持数据库:

2.环境搭建及入门

2.1 创建一个springboot项目

2.2 创建表

2.3检查pom.xml依赖

2.4 application.yml配置

2.5 实体类

2.6 其他代码

启动类

测试类

2.7 测试结果

3.实战

3.1 查询篇

3.1.1 常用查询

3.1.2 自定义sql

方案一 注解方式

测试方法:

方案二 XML形式 Mapper.xml

application.yml配置(增加日志输出和mapper目录指定的配置)

Dao类代码

测试类

3.1.3 分页查询

1. selectPage方法

2. selectMapsPage方法

3.2 修改篇

updateById 根据id修改用户信息

update通过条件修改用户信息

通过条件修改用户信息(需要修改的字段少,可通过这种方式)

通过条件修改用户信息(lambda方式,强烈推荐)

lambda链表方式,根据条件修改用户记录

3.3 删除篇

根据id删除对应的用户记录

根据id批量删除

根据map里面的条件,删除对应的数据

lambda链表方式实现通过条件删除对应数据

lambda通过条件删除对应数据

3.4 插入篇

插入用户信息

批量插入

不存在则新增,新增则修改

3.5逻辑删除篇

实体类变动

测试代码

查询的数据排除标识逻辑位

3.6自动填充篇

表结构变动

实体类变动

自动填充的类

测试类


 

前言

过年在家没有事做,待在家就是为国做贡献,武汉加油,中国加油,花了一点时间整理了一下mybatis plus集成springboot。

1.Mybatis plus简介

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。例如aop里面的环绕增强类似

1.1特点:

无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

1.2支持数据库:

mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver

2.环境搭建及入门

2.1 创建一个springboot项目

 


 


 


输入项目的x,y坐标。点击下一步。

 


 


可以修改对应工作空间目录。点击finish
耐心的等待一段时间,这段时间在下载springboot的一些依赖包

 


如果,发现下载速度很卡,可以到maven conf里面的setting文件里,增加阿里云镜像。
项目创建完成。

 

2.2 创建表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '小短腿鲁班', 18, 'test1@baomidou.com', '2020-01-30 17:21:56');
INSERT INTO `user` VALUES (2, '站撸王后羿', 20, 'test2@baomidou.com', '2020-01-30 17:21:59');
INSERT INTO `user` VALUES (3, '隐身兰陵王', 28, 'test3@baomidou.com', '2020-01-30 17:22:02');
INSERT INTO `user` VALUES (4, '98k百里守约', 20, 'test4@baomidou.com', '2020-01-15 17:22:04');
INSERT INTO `user` VALUES (5, '钩子哥钟馗', 24, 'test5@baomidou.com', '2020-01-08 17:22:08');

SET FOREIGN_KEY_CHECKS = 1;

2.3检查pom.xml依赖

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.cxyxs</groupId>
    <artifactId>mybatisplus</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatisplus</name>
    <description>Demo project for Spring Boot</description>

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

    <dependencies>
        <!--web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--junit测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.0</version>
        </dependency>

        <!--简化代码插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>

        <!-- druid阿里巴巴数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>

        <!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.4 application.yml配置

server:
  port: 8888

spring:
  datasource:
    # 配置数据源
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 使用druid连接池
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://127.0.0.1:3306/pro?useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
    username: root
    password: root

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

注意:修改成自己对应的配置。配置mybatis-plus对应的日志,方便定位问题(开发环境使用)。

 


例如,上述代码转换成的sql为如下,这样就方面定位问题,项目开发中,日志格式输出也要规范,好的日志规范,能提高我们的开发效率。

 

2.5 实体类

通过工具实现代码自动生成

package com.cxyxs.mybatisplus.entity;

import lombok.Data;

import java.util.Date;

@Data
public class User {
    private Integer id;

    private String name;

    private Integer age;

    private String email;

    private Date createTime;
}

@Data注解,就是使用lombok的插件,简化代码

2.6 其他代码

package com.cxyxs.mybatisplus.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cxyxs.mybatisplus.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Mapper
@Repository  //记得加上这个注解,不然,@Autowired会报红,但是可以查询数据
public interface UserMapper extends BaseMapper<User> {
}

启动类

package com.cxyxs.mybatisplus;

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

@SpringBootApplication
@MapperScan("com.cxyxs.mybatisplus.dao")
public class MybatisplusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisplusApplication.class, args);
    }

}

测试类

package com.cxyxs.mybatisplus;

import com.cxyxs.mybatisplus.entity.User;
import com.cxyxs.mybatisplus.mapper.UserMapper;
import org.junit.jupiter.api.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;

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

    @Test
    void contextLoads() {
    }


    /**
     * 查询所有数据
     */
    @Test
    void select() {
        List<User> list= userMapper.selectList(null);
        list.forEach(System.out::println);
    }
}

注意:使用了junit,不了解的可以百度一下

2.7 测试结果

 


到这里,mybatils plus入门的小demo就成功。说明我们的配置整体的配置都没有问题。

 

3.实战

说再多,看再多,还不如自己动手。这是社长我一直坚信的一点。

3.1 查询篇

 


这是所有的查询方法,具体可以通过查看他的源码,都有中文注释,再也不要跟社长会,我看不懂。。

 

3.1.1 常用查询

package com.cxyxs.mybatisplus;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cxyxs.mybatisplus.entity.User;
import com.cxyxs.mybatisplus.dao.UserMapper;
import org.junit.jupiter.api.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.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 程序猿学社
 */
@RunWith(SpringRunner.class)
@SpringBootTest
class MybatisplusApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
    }


    /**
     * 查询所有数据
     */
    @Test
    void select() {
        List<User> list= userMapper.selectList(null);
        list.forEach(System.out::println);
    }

    /**
     * 查询根据id返回对象
     */
    @Test
    void selectById(){
        User user = userMapper.selectById(1);
        System.out.println(user.toString());
    }

    /**
     * 根据List的id集合查询对应的用户list
     */
    @Test
    void selectBatchIds(){
        List<User> list = userMapper.selectBatchIds(Arrays.asList(1,2,10));
        list.forEach(System.out::println);
    }

    @Test
    void selectByMap(){
        Map<String, Object> map = new HashMap<>();
        map.put("age","20");
        //查询年龄为20岁的所有用户,可以拼接多个值
        //注意:建议尽量减少使用map这种方式。因为可能字段名可能存在修改的情况,如果,项目开发一段时间后,再修改,影响太大
        List<User> list = userMapper.selectByMap(map);
        list.forEach(System.out::println);
    }

    /**
     * 查询大于20岁的学生,名称中包含小的人,带条件判断的,可以采用这种方式
     * SELECT id,name,age,email,create_time FROM user WHERE (name LIKE ? AND age > ?)
     */
    @Test
    void selectListWrapper(){
        //类似于hibernate
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name","小");
        queryWrapper.gt("age", "17");
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }

    /**
     * 模糊查询名称包含王,年龄大于18,通过Lambda方式
     * 强烈推荐这种方式:因为他是通过调用字段对应的get方法,实现跟数据库字段的一个映射
     * 而不想之前的代码,key都是实体类的字符串的字段名,万一,字段有变动,根本就无法知道哪里有变动。
     */
    @Test
    void lambdaQueryWrapper(){
        LambdaQueryWrapper<User> query = Wrappers.<User>lambdaQuery();
        query.like(User::getName,"王").gt(User::getAge,18);
        //.gt(User::getAge, 20);
        List<User> list = userMapper.selectList(query);
        list.forEach(System.out::println);
    }
}

3.1.2 自定义sql

注意:mybatis-plus版本需大于等于3.0.7,才支持自定义sql

方案一 注解方式

package com.cxyxs.mybatisplus.dao;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.cxyxs.mybatisplus.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository  //记得加上这个注解,不然,@Autowired会报红,但是可以查询数据
public interface UserMapper extends BaseMapper<User> {
    @Select("select * from user ${ew.customSqlSegment}")
    List<User> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);
}

测试方法:

/**
 * 获取自定义的MP(注解版本)
 */
@Test
void getAll(){
    LambdaQueryWrapper<User> query = Wrappers.<User>lambdaQuery();
    query.like(User::getName,"王").gt(User::getAge,18);
    //.gt(User::getAge, 20);
    List<User> list = userMapper.getAll(query);
    list.forEach(System.out::println);
}

方案二 XML形式 Mapper.xml

UserMapper.xml

<?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="com.cxyxs.mybatisplus.dao.UserMapper">
    <select id="getXml" resultType="com.cxyxs.mybatisplus.entity.User">
    select * from User  ${ew.customSqlSegment}
    </select>
</mapper>

application.yml配置(增加日志输出和mapper目录指定的配置)

###增加日志输出,方便定位问题
logging:
  level:
    root : warn
    com.cxyxs.mybatisplus.dao: trace
  ###控制台输出格式
  pattern:
    console: '%p%m%n'

mybatis-plus:
  mapper-locations: classpath*:/com/cxyxs/mybatisplus/mapper/*.xml

Dao类代码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.cxyxs.mybatisplus.dao;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cxyxs.mybatisplus.entity.User;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

@Repository
public interface UserMapper extends BaseMapper<User> {
    List<User> getXml(@Param("ew") Wrapper wrapper);
}

测试类

/**
 * 获取自定义的MP(xml版本)
 */
@Test
void getAllXml(){
    LambdaQueryWrapper<User> query = Wrappers.<User>lambdaQuery();
    query.like(User::getName,"王").gt(User::getAge,18);
    //.gt(User::getAge, 20);
    List<User> list = userMapper.getXml(query);
    list.forEach(System.out::println);
}

运行junit发现有如下报错?

 


卡了社长不短的时间,查了一段时间,才发现编译后的目录里面没有mapper文件?why?
解决方法:需要再build文件中如下代码。

 

<resources>
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.xml</include>
        </includes>
    </resource>
</resources>

划重点:mapper文件包,如果在resources目录下,就可以不加。

3.1.3 分页查询

package com.cxyxs.mybatisplus.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Description:mybatis-plus插件
 * Author: 程序猿学社
 * Date:  2020/2/2 15:26
 * Modified By:
 */
@Configuration
public class MyBatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}

1. selectPage方法

/**
 * 分页查询
 */
@Test
void getSelectPage(){
    LambdaQueryWrapper<User> query = Wrappers.<User>lambdaQuery();
    //第一个参数表示当前页
    //第二个参数表示当前页显示多少条
    //第三个参数是否查询count
    Page<User> page = new Page<>(2, 2,false);
    Page<User> userPage = userMapper.selectPage(page, query);
    //需要需要获取总记录数或者总页数,可以自己查看Page源码里面都有那些字段
    List<User> records = userPage.getRecords();
    records.forEach(System.out::println);
}

 


通过日志,我们可以自动,分页插件,一个分页,需要查两次,一次查count,还有一次查对应的数据。
扩展:
学习了mybatis-plus后,发现他只是对sql做一个增强,通过这种方式,例如,做权限管理系统,通过权限控制数据,深圳市的管理,只能看深圳的数据,广东省的管理只能看广东省的数据,全国的管理,可以看全国的数据,我们就可以通过增强实现。在写好的sql后,通过mybatis-plus类似的方式,把权限的条件拼接上,这样我们的代码,就更好维护。学习就是主要是还是学习别人的思想,这样我们才能有大的提升。

 

2. selectMapsPage方法

/**
 * 分页查询 Map方式
 */
@Test
void getSelectMapsPage(){
    QueryWrapper<User> query = new QueryWrapper<User>();
    //第一个参数表示当前页
    //第二个参数表示当前页显示多少条
    Page<Map<String,Object>> page = new Page<>(2, 2);
    IPage<Map<String, Object>> maps = userMapper.selectMapsPage(page,query);
    maps.getRecords().forEach(System.out::println);
}

3.2 修改篇

updateById 根据id修改用户信息

/**
 * 根据id修改用户信息
 */
@Test
void updateUserById(){
    User user = new User();
    user.setId(1);
    user.setName("小短腿鲁班-程序猿学社");
    int result = userMapper.updateById(user);
    System.out.println(result>0 ? "修改成功":"修改失败");
}

update通过条件修改用户信息

/**
 * 通过条件修改用户信息
 */
@Test
public void updateWrapper(){
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.eq("age","18");

    User user = new User();
    user.setName("小短腿鲁班-程序猿学社123");
    int result = userMapper.update(user, wrapper);
    System.out.println(result>0 ? "修改成功":"修改失败");
}

通过条件修改用户信息(需要修改的字段少,可通过这种方式)

/**
 * 通过条件修改用户信息(需要修改的字段少,可通过这种方式)
 */
@Test
public void updateWrapper1(){
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.eq("age","18").set("name","小短腿鲁班-程序猿学社456");

    int result = userMapper.update(null, wrapper);
    System.out.println(result>0 ? "修改成功":"修改失败");
}

通过条件修改用户信息(lambda方式,强烈推荐)

/**
 * 通过条件修改用户信息(需要修改的字段少,可通过这种方式)
 * 强烈推荐,避免出错
 */
@Test
public void updatelamWrapper(){
    LambdaUpdateWrapper<User> updateWrapper = Wrappers.<User>lambdaUpdate();
    updateWrapper.eq(User::getAge,"18").set(User::getName,"小短腿鲁班-程序猿学社789");

    int result = userMapper.update(null, updateWrapper);
    System.out.println(result>0 ? "修改成功":"修改失败");
}

lambda链表方式,根据条件修改用户记录

/**
 * lambda链表方式,根据条件修改用户记录
 */
@Test
public void updatelambdaWrapper(){
    boolean result = new LambdaUpdateChainWrapper<>(userMapper)
            .eq(User::getAge, "18").set(User::getName, "小短腿鲁班-程序猿学社1314").update();
    System.out.println(result ? "修改成功":"修改失败");
}

3.3 删除篇

根据id删除对应的用户记录

/**
 * 根据id删除对应的用户记录
 */
@Test
public void deleteById(){
    int result = userMapper.deleteById(6);
    System.out.println(result>0 ? "删除成功":"删除失败");
}

根据id批量删除

/**
 * 根据id批量删除
 */
@Test
public void deleteBatchIds(){
    int result = userMapper.deleteBatchIds(Arrays.asList(6, 7, 8));
    System.out.println("批量删除条数:"+result);
}

根据map里面的条件,删除对应的数据

/**
 * 根据map里面的条件,删除对应的数据
 */
@Test
public void deleteByMap(){
    Map<String,Object> map = new HashMap<>();
    map.put("age","38");
    int result = userMapper.deleteByMap(map);
    System.out.println(result>0 ? "删除成功":"删除失败");
}

lambda链表方式实现通过条件删除对应数据

/**
 * lambda链表方式实现通过条件删除对应数据
 */
@Test
public void deleteChainWrapper(){
    boolean remove = new LambdaUpdateChainWrapper<>(userMapper).eq(User::getAge, 39).remove();
    System.out.println(remove ? "删除成功":"删除失败");
}

lambda通过条件删除对应数据

/**
 * lambda通过条件删除对应数据
 */
@Test
public void deleteWrapper(){
    LambdaQueryWrapper<User> lambdaQuery= Wrappers.<User>lambdaQuery();
    lambdaQuery.eq(User::getAge, 39);
    int result = userMapper.delete(lambdaQuery);
    System.out.println(result>0 ? "删除成功":"删除失败");
}

3.4 插入篇

数据库是自动增长,设置实体类也为自增长模式

 

插入用户信息

/**
 * 新增用户信息
 */
@Test
public void insert(){
    User user = new User();
    user.setName("程序猿学社123");
    user.setAge(11);
    user.setCreateTime(new Date());
    user.setEmail("1024@qq.com");
    int result = userMapper.insert(user);
    System.out.println(result>0 ? "新增成功":"新增失败");
}

 


 


发现插入的时间和数据库的时间有时差?
serverTimezone=GMT%2B8

 

 

批量插入

package com.cxyxs.mybatisplus.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.cxyxs.mybatisplus.entity.User;
import org.springframework.stereotype.Service;
/**
 * Description:
 * Author: 程序猿学社
 * Date:  2020/2/2 18:47
 * Modified By:
 */
@Service
public interface UserService extends IService<User> {

}
package com.cxyxs.mybatisplus.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cxyxs.mybatisplus.dao.UserMapper;
import com.cxyxs.mybatisplus.entity.User;
import com.cxyxs.mybatisplus.service.UserService;
import org.springframework.stereotype.Service;

/**
 * Description:
 * Author: 程序猿学社
 * Date:  2020/2/2 18:51
 * Modified By:
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
/**
 * 批量插入
 */
@Test
public void saveBatch(){
   System.out.println("123");
    List<User> users = new ArrayList<>();
    for(int i=0;i<5;i++){
        User user = new User();
        user.setName("程序猿学社"+i);
        user.setAge(11);
        user.setCreateTime(new Date());
        user.setEmail("1024@qq.com");
        users.add(user);
    }
    boolean result = userService.saveBatch(users);
    System.out.println(result ? "批量新增成功":"批量新增失败");
}

不存在则新增,新增则修改

/**
 * 不存在则新增,新增则修改
 */
@Test
public void saveOrUpdate(){
    User user = new User();
    user.setName("程序猿学社520");
    user.setAge(11);
    user.setCreateTime(new Date());
    user.setEmail("1024@qq.com");
    user.setId(21);
    boolean result = userService.saveOrUpdate(user);
    System.out.println(result ? "成功":"失败");
}

3.5逻辑删除篇

逻辑删除实际上就是假删除。在数据表中,通过一个字段标识该字段是否已删除
表结构变动,增加一个是否删除的字段

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `is_delete` int(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;

实体类变动

 


增加@TableLogin注解标识该字段是逻辑位字段。

 

测试代码

/**
 * 根据id删除对应的用户记录
 */
@Test
public void deleteById(){
    int result = userMapper.deleteById(21);
    System.out.println(result>0 ? "删除成功":"删除失败");
}

 


通过测试,我们可以发现,我们明明跑到删除语句,但是,底层会给我们拼上is_delete=0,只有标识位为0的数据,我们才能删除。新增,修改都是同上,注意:我们自己写的mybatis文件里面的sql,不会补上。

 

查询的数据排除标识逻辑位

有社友反馈说,每次查询,返回都返回标识位,太浪费了,能不能把逻辑位,不显示出来,当然可以呀

@Test
void selectById(){
    User user = userMapper.selectById(22);
    System.out.println(user.toString());
}

 


改进方案:
增加该注解

 


 


再次查询,我们可以看到,没有is_delete字段了
注意:自己写的mybatils的sql语法,如果写了is_delete字段,返回还会有值。这里所有的注解,只是针对mybatis-plus他自己实现的语法而言。

 

3.6自动填充篇

表结构变动

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL,
  `is_delete` int(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;

实体类变动

 

 

自动填充的类

package com.cxyxs.mybatisplus.config;

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

import java.util.Date;

/**
 * Description:
 * Author: 程序猿学社
 * Date:  2020/2/2 21:02
 * Modified By:
 */
@Component
public class AutoFill  implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        //考虑到没有createTime字段,也执行了,所以,这里需要增加判断
        boolean flag = metaObject.hasGetter("createTime");
        if(flag){
            setFieldValByName("createTime",new Date(),metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        Object flag = getFieldValByName("updateTime",metaObject);
        //如果有给修改时间赋值,就不用给该字段赋值
        if(flag == null){
            setFieldValByName("updateTime",new Date(),metaObject);
        }
    }
}

测试类

/**
 * 新增用户信息
 */
@Test
public void insert(){
    User user = new User();
    user.setName("程序猿学社456");
    user.setAge(11);
    user.setEmail("1024@qq.com");
    int result = userMapper.insert(user);
    System.out.println("id为:"+user.getId());
    System.out.println(result>0 ? "新增成功":"新增失败");
}

/**
 * 根据id修改用户信息
 */
@Test
void updateUserById(){
    User user = new User();
    user.setId(1);
    user.setName("小短腿鲁班-程序猿学社");
user.setUpdateTime(new Date());
    int result = userMapper.updateById(user);
    System.out.println(result>0 ? "修改成功":"修改失败");
}

这里设置了修改时间,就不用跑填充的类

源码

 

博主,java小白,有问题欢迎在下方留言。大家互相交流,互相进步!
每周更新,分享各个技术点面试、结构和算法、源码分析等干货

 

发布了289 篇原创文章 · 获赞 1018 · 访问量 35万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览