当前位置:   article > 正文

Mybatis-Plus 从入门到精通

Mybatis-Plus 从入门到精通

Mybatis-plus

快速入门

首先 先导入包

    <dependencies>
<!--        数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
<!--        工具包  可以帮助生成get set 之类的-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

<!--        mybatis-plus-->
        <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.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

如果导入mybatis-plus是3.0.7版本以上的需要导入

<!--        3.0.7版本移除 对 mybatis-plus-generator 包的依赖,自己按需引入,尽在还需要导入模板依赖,-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

导入数据库的数据

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)
);

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

配置 配置文件

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/mybatis-plus?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这样准备工作就完成了

上代码

创建一个对象 对应数据库中的表

import lombok.Data;

@Data
public class User {

    private Long id;
    private String name;
    private Integer age;
    private String email;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Mapper文件

我们只需要继承BaseMappe 在BaseMappe里面 他帮我们实现了大部分的CRUD 不需要我们再写了

在这里可以看见我们只继承了BaseMappe 别的什么都没写

@Repository
public interface UserMapper extends BaseMapper<User> {

}
  • 1
  • 2
  • 3
  • 4

启动类

@SpringBootApplication
@MapperScan("com.bbaa.mapper")
public class MybatisPiusDemo01Application {

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

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

测试

@SpringBootTest
class MybatisPiusDemo01ApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
    }

    @Test
    public void test1(){
		//UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

结果

User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)
  • 1
  • 2
  • 3
  • 4
  • 5

配置日志

配置日志只需要在配置文件中加上就可以了

#配置日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 1
  • 2
  • 3
  • 4
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7a4d582c] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1775488894 wrapping com.mysql.cj.jdbc.ConnectionImpl@3a3ed300] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email FROM user 
==> Parameters: 
<==    Columns: id, name, age, email
<==        Row: 1, Jone, 18, test1@baomidou.com
<==        Row: 2, Jack, 20, test2@baomidou.com
<==        Row: 3, Tom, 28, test3@baomidou.com
<==        Row: 4, Sandy, 21, test4@baomidou.com
<==        Row: 5, Billie, 24, test5@baomidou.com
<==      Total: 5

Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7a4d582c]
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

CRUD扩展

select查询

根据id查询单条数据
	public void testOptimisticLocker(){
        //因为id是long类型的  所以数字后面加上了L
        User user = userMapper.selectById(1L);
    	System.out.println(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
User(id=1, name=Jone, age=18, email=test1@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
  • 1
查询多条数据
@Test
    public void testselect(){
        //selectBatchIds需要传入的是list集合
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
        users.forEach(System.out::println);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
User(id=1, name=Jone, age=18, email=test1@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
User(id=2, name=Jack, age=20, email=test2@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
User(id=3, name=Tom, age=28, email=test3@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
  • 1
  • 2
  • 3
条件查询之 map
//条件查询  map
    @Test
    public void selectByMap(){
        HashMap<String ,Object> map = new HashMap<>();
        //放入自定义条件  比如:我要查询 年龄为20用户的信息
        map.put("age",20);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
User(id=2, name=Jack, age=20, email=test2@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
User(id=4, name=Sandy, age=20, email=test4@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
User(id=7, name=ww, age=20, email=ava@qq.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
  • 1
  • 2
  • 3
分页

在page对象中 对分页的常用操作 都有

总数,上一页,下一页,排序 等等…

 //分页
    @Test
    public void testpage(){
        //参数一:第几页
        // 参数二:每页显示的条数
        Page<User> userPage = new Page<>(1,5);
        //参数一:页查询条件(可以为 RowBounds.DEFAULT)
        //参数二:实体对象封装操作类(可以为 null)
        Page<User> userPage1 = userMapper.selectPage(userPage, null);
        //打赢
        userPage1.getRecords().forEach(System.out::println);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
User(id=1, name=Jone, age=18, email=test1@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
User(id=2, name=Jack, age=20, email=test2@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
User(id=3, name=Tom, age=28, email=test3@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
User(id=4, name=Sandy, age=20, email=test4@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
User(id=5, name=Billie, age=24, email=test5@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1)
  • 1
  • 2
  • 3
  • 4
  • 5

insert插入

  @Test
    public void insert(){
        //创建user
        User user = new User();
        user.setName("zs");
        user.setAge(20);
        user.setEmail("aaa@qq.com");
		//添加
        int insert = userMapper.insert(user);
		//打印
        System.out.println(insert);
        System.out.println(user);

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
JDBC Connection [HikariProxyConnection@1357597228 wrapping com.mysql.cj.jdbc.ConnectionImpl@1a256d80] will not be managed by Spring
    
==>  Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) 
==> Parameters: 1401036342073540610(Long), zs(String), 20(Integer), aaa@qq.com(String)
<==    Updates: 1
    
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35c9a231]
    
1
    
User(id=1401036342073540610, name=zs, age=20, email=aaa@qq.com)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

从代码中可以看出我们没有添加id 但在控制台输出 却有一个id 1401036342073540610 并且user中 也存在了id

这说明 userMapper.insert(user) 不仅帮我们创建了全局唯一id 而且还把id的值给了user对象

主键生成策略

分布式系统唯一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。具体实现的代码可以参看https://github.com/twitter/snowflake。雪花算法支持的TPS可以达到419万左右(2^22*1000)。

雪花算法在工程实现上有单机版本和分布式版本。单机版本如下,分布式版本可以参看美团leaf算法:https://github.com/Meituan-Dianping/Leaf

@Data
public class User {

    //对应数据库中的组件 (uuid,自增id,雪花算法,redis,zookeeper)
    //如果是用的自增 数据库中的id也必须设置为自增
    @TableId(type = IdType.ID_WORKER)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

public enum IdType {
   /**
     * 数据库ID自增
     */
    AUTO(0),
    /**
     * 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
     */
    NONE(1),
    /**
     * 用户输入ID
     * <p>该类型可以通过自己注册自动填充插件进行填充</p>
     */
    INPUT(2),

    /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
    /**
     * 分配ID (主键类型为number或string),
     * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
     *
     * @since 3.3.0
     */
    ASSIGN_ID(3),
    /**
     * 分配UUID (主键类型为 string)
     * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
     */
    ASSIGN_UUID(4),
    /**
     * @deprecated 3.3.0 please use {@link #ASSIGN_ID}
     */
    @Deprecated
    ID_WORKER(3),
    /**
     * @deprecated 3.3.0 please use {@link #ASSIGN_ID}
     */
    @Deprecated
    ID_WORKER_STR(3),
    /**
     * @deprecated 3.3.0 please use {@link #ASSIGN_UUID}
     */
    @Deprecated
    UUID(4);

    private final int key;

    IdType(int key) {
        this.key = key;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

更新(修改 updata)

    @Test
    public void updata(){
        User user = new User();
        user.setId(6L);//因为是long类型的 所以结尾要加上 L
        user.setName("ls");
        user.setAge(30);
        user.setEmail("bbb@qq.com");
		//修改
        //int updateById(@Param("et") T entity);
        //传入的参数是一个对象  而不是id
        int i = userMapper.updateById(user);
		//打印
        System.out.println(i);
        System.out.println(user);

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

修改前

在这里插入图片描述

修改后
在这里插入图片描述

结果

JDBC Connection [HikariProxyConnection@438660480 wrapping com.mysql.cj.jdbc.ConnectionImpl@3069a360] will not be managed by Spring

==>  Preparing: UPDATE user SET name=?, age=?, email=? WHERE id=? 
==> Parameters: ls(String), 30(Integer), bbb@qq.com(String), 6(Long)
<==    Updates: 1
    
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5626d18c]
//受影响的行数   
1
//user
User(id=6, name=ls, age=30, email=bbb@qq.com)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在控制台可以看出 我们修改了id为6 的用户信息

自动填充(比如:时间)

我们先在数据库中 创建两个字段 create_time 创建时间 ,update_time修改时间

在这里插入图片描述

把user类中 添加两个属性

    private Data createTime;
    private Data updateTime;
  • 1
  • 2

怎么实现自动插入和更新时间呢?

    /**
     * 插入时填充字段
     */
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    /**
     * 更新时填充字段
     */
    @TableField(fill = FieldFill.UPDATE)
    private LocalDateTime updateTime;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

编写处理器来处理这个注解

在官网上有教程 : https://mp.baomidou.com/guide/auto-fill-metainfo.html

@Slf4j//日志
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    //插入时候的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("插入时候的填充策略");
        //这里LocalDateTime 是要和属性的类型对应
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); 
        this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());

    }
    //更新时候的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("更新时候的填充策略");
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); 
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
@TableField
    /**
     * 字段自动填充策略
     */
    FieldFill fill() default FieldFill.DEFAULT;


//FieldFill类
public enum FieldFill {
    /**
     * 默认不处理
     */
    DEFAULT,
    /**
     * 插入时填充字段
     */
    INSERT,
    /**
     * 更新时填充字段
     */
    UPDATE,
    /**
     * 插入和更新时填充字段
     */
    INSERT_UPDATE
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

乐观锁

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

悲观锁:与乐观锁相反 干什么都要上锁 再去操作

举例

有A B两个人同时在修改系统
当前这个系统的版本 version = 1.0 版本
A 在修改系统以后需要在版本改为1.1
updata user set name = 'zs',version = version + 0.1 where id = 10 and version = 1.0
B也在修改系统 
updata user set name = 'zs',version = version + 0.1 where id = 10 and version = 1.0
这个时候 A先完成 把系统升级为version = 1.1版本了 B修改就失败了 B只有重新去获取当前版本的值来查询修改
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

实战

现在数据库中添加 version字段

在这里插入图片描述

实体类添加字段

    //版本号
    @Version//乐观锁
    private Double version;
  • 1
  • 2
  • 3
测试乐观锁成功的情况
//测试乐观锁成功的情况
    @Test
    public void testOptimisticLocker(){
        //查询用户信息
        User user = userMapper.selectById(6L);
        //修改用户信息
        user.setName("zs");
        user.setAge(40);
        //执行修改操作
        userMapper.updateById(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

结果


==>  Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id=? 
==> Parameters: 6(Long)
<==    Columns: id, name, age, email, create_time, update_time, version
<==        Row: 6, ls, 30, bbb@qq.com, 2021-06-05 13:46:12, 2021-06-05 13:46:12, 1.00
<==      Total: 1

    //在这里WHERE id=? AND version=?  可以看出判断了版本号是否是1.0版本
==>  Preparing: UPDATE user SET name=?, age=?, email=?, create_time=?, update_time=?, version=? WHERE id=? AND version=? 
    
==> Parameters: zs(String), 40(Integer), bbb@qq.com(String), 2021-06-05T13:46:12(LocalDateTime), 2021-06-05T13:46:12(LocalDateTime), 1.0(Double), 6(Long), 1(Integer)
    
<==    Updates: 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
测试乐观锁失败的情况
    //测试乐观锁失败的情况
    @Test
    public void testOptimisticLocker2(){
        //查询用户信息
        User user = userMapper.selectById(6L);
        User user2 = userMapper.selectById(6L);

        //A:修改用户信息
        user.setName("zs");
        user.setAge(40);

        //B:修改用户信息
        user2.setName("kk");
        user2.setAge(30);

        //执行修改操作
        userMapper.updateById(user2);
        //如果没有乐观锁的情况下  下面的这一条数据会把上面的数据给覆盖
        userMapper.updateById(user);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

结果

//user的
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id=? 
==> Parameters: 6(Long)
<==    Columns: id, name, age, email, create_time, update_time, version
<==        Row: 6, zs, 40, bbb@qq.com, 2021-06-05 13:46:12, 2021-06-05 13:46:12, 1
<==      Total: 1

//user2的
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id=? 
==> Parameters: 6(Long)
<==    Columns: id, name, age, email, create_time, update_time, version
<==        Row: 6, zs, 40, bbb@qq.com, 2021-06-05 13:46:12, 2021-06-05 13:46:12, 1
<==      Total: 1

//编译时  user2的
==>  Preparing: UPDATE user SET name=?, age=?, email=?, create_time=?, update_time=?, version=? WHERE id=? AND version=? 
==> Parameters: kk(String), 30(Integer), bbb@qq.com(String), 2021-06-05T13:46:12(LocalDateTime), 2021-06-05T13:46:12(LocalDateTime), 2(Integer), 6(Long), 1(Integer)
<==    Updates: 1

//编译时  user的 
==>  Preparing: UPDATE user SET name=?, age=?, email=?, create_time=?, update_time=?, version=? WHERE id=? AND version=? 
==> Parameters: zs(String), 40(Integer), bbb@qq.com(String), 2021-06-05T13:46:12(LocalDateTime), 2021-06-05T13:46:12(LocalDateTime), 2(Integer), 6(Long), 1(Integer)
    //影响的行数 0 说明添加失败
<==    Updates: 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

删除操作

在这里插入图片描述

删除单条数据 根据id

//删除
    //删除单条数据 根据id
    //条件查询  map
    @Test
    public void deleteById(){
        int i = userMapper.deleteById(6L);
        System.out.println(i);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
==>  Preparing: DELETE FROM user WHERE id=? 
==> Parameters: 6(Long)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@73971965]
1
  • 1
  • 2
  • 3
  • 4
  • 5

其他操作其实和select里面的操作一样

逻辑删除

物理删除:直接把数据库中的数据给删除

逻辑删除:在数据库中没有移除数据,只是让用户不再查询到 通过一个变量让数据失效 delete = 0 -> delete = 1

在一些网站上管理员可以查看被删除的数据 这些就是通过逻辑删除

逻辑删除可以防止数据的丢失 类似于回收站

我们现在数据库中添加 deletes字段 注意 不要使用delete当做字段名 会出错 关键词
在这里插入图片描述

在这里插入图片描述

给user对象添加 deletes属性

    @TableLogic//逻辑删除
    private Integer deletes;
  • 1
  • 2

在配置文件中 添加逻辑删除的配置

mybatis-plus:
    #逻辑删除
  global-config:
    db-config:
      logic-delete-field: flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置@TableLogic)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

测试

   //逻辑删除
    @Test
    public void testdelete(){
        int i = userMapper.deleteById(9L);
        System.out.println(i);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
==>  Preparing: UPDATE user SET deletes=1 WHERE id=? AND deletes=0 //这里加上了一个条件 deletes=0 代表这条数据是没有被删除过的
==> Parameters: 9(Long)
<==    Updates: 1
//受影响的行数
1
  • 1
  • 2
  • 3
  • 4
  • 5

在这里我们可以看出 调用的其实是update方法

在这里插入图片描述

数据库中数据没有被删除 但delete被修改为1

我们再进行查询 看看是否还可以被查询出来

		User user = userMapper.selectById(9L);
        System.out.println(user);
  • 1
  • 2
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version,deletes FROM user WHERE id=? AND deletes=0 
==> Parameters: 9(Long)
<==      Total: 0  //0条数据
  • 1
  • 2
  • 3

可以看出 是没有被查询出来的 因为在判断条件中 添加了deletes=0

性能分析插件

这个可以帮助我们测试sql运行的时间

在3.3.2版本以后 官方删除了性能分析插件

感兴趣的小伙伴可以百度查看

Wrapper条件构造器

警告:

不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输

  1. wrapper 很重
  2. 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
  3. 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
  4. 拒绝接受任何关于 RPC 传输 Wrapper 报错相关的 issue 甚至 pr

QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件

测试一:查询姓名不为null 并且 年龄大于或等于20岁的人

    @Test
    public void test(){
        //设置条件查询 查询一般使用QueryWrapper对象
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //isNotNull("name")---sql语句里面--->name is not null
        wrapper.isNotNull("name")//name不为null
                //ge("age", 18)---sql语句里面--->age >= 18
                .ge("age",20);//age大于或者等于20岁
        userMapper.selectList(wrapper).forEach(System.out::println);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version,deletes FROM user WHERE deletes=0 AND (name IS NOT NULL AND age >= ?) 
==> Parameters: 20(Integer)
    
User(id=2, name=Jack, age=20, email=test2@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1, deletes=0)
User(id=3, name=Tom, age=28, email=test3@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1, deletes=0)
User(id=4, name=Sandy, age=20, email=test4@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1, deletes=0)
User(id=5, name=Billie, age=24, email=test5@baomidou.com, createTime=2021-06-05T13:46:12, updateTime=2021-06-05T13:46:12, version=1, deletes=0)
User(id=10, name=ww, age=23, email=ava@qq.com, createTime=2021-06-06T10:24:07, updateTime=2021-06-06T10:24:07, version=1, deletes=0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

测试二:查询姓名为ww的人

    @Test
    public void test2(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //eq:eq("name", "老王")---sql语句里面--->name = '老王'
        wrapper.eq("name","ww");//姓名为ww
        userMapper.selectList(wrapper).forEach(System.out::println);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

测试三:插叙年龄在id>4的


    @Test
    public void test3(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //字段 IN ( sql语句 )
        //例: inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6)
        //例: inSql("id", "select id from table where id > 4")--->id in (select id from table where id > 4)
       
        wrapper.inSql("id","select id from user where id >4");//重点
        userMapper.selectList(wrapper).forEach(System.out::println);

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

代码生成器

导入包

<!--        3.0.3 版本移除 需自己引入,添加 模板引擎 依赖-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>

<!--        添加 代码生成器 依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

配置的代码

package com.jiang;

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 org.springframework.boot.test.context.SpringBootTest;

import java.util.ArrayList;

@SpringBootTest
public class DMcode {

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        //获取到用户当前的目录
        String projectPath = System.getProperty("user.dir");
        //生成的地址
        gc.setOutputDir(projectPath + "/src/main/java");
        //生成作者信息
        gc.setAuthor("jiang");
        //是否打开文件夹
        gc.setOpen(false);
        //是否覆盖之前生成的文件
        gc.setFileOverride(false);
        //默认的初始算法  id
        gc.setIdType(IdType.ID_WORKER);
        //配置日期的类型
//        gc.setDateType(DateType.ONLY_DATE);
        // gc.setSwagger2(true); 是否配置swagger文档

        //全局配置放在代码生成器中
        mpg.setGlobalConfig(gc);

        //设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mybatis-plus?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        //数据库类型 mysql
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        //模块名
        pc.setModuleName("plus");
        //在哪个包下面生成模块
        pc.setParent("com.jiang.demo");
        //实体类的名字
        pc.setEntity("pojo");
        //mapper类
        pc.setMapper("mapper");
        //设置为servic层的名称
        pc.setService("service");
        //设置controller层名称
        pc.setController("controller");
        mpg.setPackageInfo(pc);


        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        //设置映射的表名
        strategy.setInclude("user");
        //设置包命名的规则  下划线转驼峰命名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        //数据库字段命名的规则  下划线转驼峰命名
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        //自动生成lombok  链式编程
        strategy.setEntityLombokModel(true);
        //设置逻辑删除
        strategy.setLogicDeleteFieldName("deletes");
        //设置自动填充字段
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updatetime = new TableFill("update_time", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> list = new ArrayList<>();
        list.add(createTime);
        list.add(updatetime);
        strategy.setTableFillList(list);
        //乐观锁
        strategy.setVersionFieldName("version");
        //设置驼峰命名
        strategy.setRestControllerStyle(true);
        //localhost:8080/hello_id_2
        strategy.setControllerMappingHyphenStyle(true);
        mpg.setStrategy(strategy);

        //执行
        mpg.execute();


    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/201462
推荐阅读
相关标签
  

闽ICP备14008679号