当前位置:
首页
文章
后端
详情

MybatisPlus的使用

MyBatisPlius

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 '邮箱',
    PRIMARY KEY (id)
);

DELETE FROM user;

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、导入依赖

    <!--数据库驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version> <!-- 使用适当的版本号 -->
</dependency>
<!--lombok-->
<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>
  • 我们使用mybaits-plus可以节省我们大量的代码,尽量不要同时导入mybatismybaits-plus

2、连接数据库

spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=PRC&characterEncoding=UTF8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3、做一个小测试

  • pojo:com.yap.mybatis_plus.mapper
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private String age;
    private String email;
}
  • mapper:com.yap.mybatis_plus.mapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yap.mybatis_plus.pojo.User;
import org.springframework.stereotype.Repository;

/**
 * @author yap
 * @version 1.0
 */
//在对应的mapper 上面继承基本的类 BaseMapper
@Repository//代表持久层
public interface UserMapper extends BaseMapper<User> {
}
  • 启动类
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//扫描mapper 文件夹
@MapperScan("com.yap.mybatis_plus.mapper")
@SpringBootApplication
public class MybatisPlusApplication {

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

}

4、测试类中

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

@Test
void selectList() {
    //参数是一个Wrapper,条件构造器,
    //查询全部用户
    List<User> users =  userMapper.selectList(null);
    users.forEach(System.out::println);
}
  • 输出结果
    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>)

5、配置日志

  • 现在是看不到sql的,配置控制台输出日志
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
  • 输出结果
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3289079a] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@324701295 wrapping com.mysql.cj.jdbc.ConnectionImpl@6419a0e1] 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@3289079a]

6、CRUD拓展

6.1 测试插入(insert)

  • insert:使用的是雪花算法生成唯一Id
  • 雪花算法:snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是: 使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID ),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个ID),最后还有一个符号位,永远是0。可以保证全球唯一!
  • 主键自增
    • 1、 :实体类字段上@TableId(type = IdType.ID_WORKER)//唯一
      • AUTO:数据库id自增
      • NONE:未设置主键
      • INPUT:手动输入
      • ID_WORKER:默认的全局唯一ID
      • UUID:全局唯一id uuid
      • ID_WORKER_STR:ID_WORKER的字符串表示法
    • 2、 :数据库字段一定要是自增否则会报错!
@Test
void insert() {
    User user = new User();
    user.setName("abc");
    user.setAge(3);
    user.setEmail("456");
    int result = userMapper.insert(user);//自动生成id
    System.out.println(result);
    System.out.println(user);
}

6.2 测试更新(update)

  • updateById:参数是一个对象
@Test
void updateById() {
    User user = new User();
    //通过条件自动拼接sql
    user.setId(1667764916303597570L);
    user.setName("123");
    user.setAge(1);
    user.setEmail("456");
    //注意updateById的参数是个对象
    int result = userMapper.updateById(user);
    System.out.println(result);
    System.out.println(user);
}

6.3 自动填充

  • 创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!
  • 阿里巴巴开发手册:所有数据库表:创建时间(gmt_create)、修改时间:(gmt_modified)几乎所有表都要配置上!而且需要自动化!

方式:代码级别

  • 1:在表中新建字段 create_time,update_time

  • 2:同步实体类User
//字段添加填充内容
@TableField(fill = FieldFill.INSERT)//代表添加的时候执行
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//代表添加修改的时候执行
private Date updateTime;
  • 3:创建com.yap.mybatis_plus.handler.MyMetaObjectHandler
  • 自定义实现类
package com.yap.mybatis_plus.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 ....");
        //插入的时候添加和修改都会存入时间
        this.strictInsertFill(metaObject, "createTime", Date.class,  new Date()); 
        this.strictInsertFill(metaObject, "updateTime", Date.class,  new Date()); 

    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        //更新的时候会修改时间
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); 
     }
}

6.4 乐观锁

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

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

  • 乐观锁实现方式:
    • 取出记录时,获取当前 version
    • 更新时,带上这个 version
    • 执行更新时, set version = newVersion where version = oldVersion
    • 如果 version 不对,就更新失败
乐观锁:1、先查询 获得版本号 version = 1
-- A
update user set name = "abc",version = version + 1
where id  = 2 and version = 1

-- B 线程抢先完成,这个时候version = 2,会导致A修改失败!
update user set name = "abc",version = version + 1
where id  = 2 and version = 1

测试一下MP乐观锁插件

  • 1、:给数据库增加version字段,默认值为1int类型,长度10
  • 2、:实体类增加字段
@Version//乐观锁version注解
private Integer version;
  • 说明:
    • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
    • 整数类型下 newVersion = oldVersion + 1
    • newVersion 会回写到 entity 中
    • 仅支持 updateById(id) 与 update(entity, wrapper) 方法
    • 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
  • 3、:测试一下!

//测试乐观锁成功
@Test
public void testVersion() {
    //1、查询用户信息
    User user = userMapper.selectById(1L);
    //2、修改用户信息
    user.setName("abc");
    user.setEmail("2314526");
    //3、执行更新操作
    int i = userMapper.updateById(user);
    System.out.println(i);
}

//测试乐观锁失败
//开启version最后数据库显示的结果是abc222
//未开启version最后数据库显示的结果是abc111
@Test
public void testVersion2() {
    //线程1
    User user = userMapper.selectById(1L);
    user.setName("abc111");
    user.setEmail("2314526");

    //模拟另外一个线程执行了插队操作
    User user2 = userMapper.selectById(1L);
    user2.setName("abc222");
    user2.setEmail("2314526");
    userMapper.updateById(user2);
    //自旋锁来多次尝试提交
    userMapper.updateById(user);//如果没有乐观锁就会覆盖插队线程的值
}

免责申明:本站发布的内容(图片、视频和文字)以转载和分享为主,文章观点不代表本站立场,如涉及侵权请联系站长邮箱:xbc-online@qq.com进行反馈,一经查实,将立刻删除涉嫌侵权内容。

同类热门文章

深入了解C++中的new操作符:使用具体实例学习

C++中的new操作符是动态分配内存的主要手段之一。在程序运行时,我们可能需要动态地创建和销毁对象,而new就是为此提供了便利。但是,使用new也常常会引发一些问题,如内存泄漏、空指针等等。因此,本文将通过具体的示例,深入介绍C++中的new操作符,帮助读者更好地掌握其使用。


深入了解C++中的new操作符:使用具体实例学习

怎么用Java反射获取包下所有类? 详细代码实例操作

Java的反射机制就是在运行状态下,对于任何一个类,它能知道这个类的所有属性和方法;对于任何一个对象,都能调用这个对象的任意一个方法。本篇文章将通过具体的代码示例,展示如何通过Java反射来获取包下的所有类。


怎么用Java反射获取包下所有类? 详细代码实例操作

了解Java中的volati关键字的作用 以及具体使用方法

本篇文章将和大家分享一下Java当中的volatile关键字,下面将为各位小伙伴讲述volatile关键字的作用以及它的具体使用方法。


了解Java中的volati关键字的作用 以及具体使用方法

Java Map 所有的值转为String类型

可以使用 Java 8 中的 Map.replaceAll() 方法将所有的值转为 String 类型: 上面的代码会将 map 中所有的值都转为 String 类型。 HashMap 是 Java

Java Map 所有的值转为String类型

员工线上学习考试系统

有点播,直播,在线支付,三级分销等功能,可以对学员学习情况的监督监控,有源码,可二次开发。支持外网和局域网私有化部署,经过测试源码完整可用!1、视频点播:视频播放,图文资料,课件下载,章节试学,限时免

员工线上学习考试系统