IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 22-07-30 西安 MybatisPlus -> 正文阅读

[Java知识库]22-07-30 西安 MybatisPlus

让自己变得稀缺的最好的办法就是让自己拥有多维度的能力,这种把多种能力结合在一起,并且为同一个目标服务,就会发挥巨大的价值。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? --------《认知红利》


mybatisplus官网?(MP)对MyBatis进一步简化

MyBatis-Plus

1、MybatisPlus入门案例

创建springboot工程mybatis-plus

1、核心依赖如下

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

    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

2、在application.properties配置文件中添加 MySQL 数据库的相关配置

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456

3、启动类

在 Spring Boot 启动类中添加?@MapperScan?注解,扫描 Mapper 文件夹

在mapper文件夹下编写Mapper接口,因为我们已经在启动类上加了@MapperScan注解,所以这里的mapper接口什么都不写也没啥问题,至于@Repository的作用,下面会说

单元测试

测试类的包名称要和启动类的包名称一致

IDEA在 userMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。

为了避免报错,可以在 dao 层 的接口上添加?@Repository?注解

import org.junit.jupiter.api.Test;

@SpringBootTest
public class MybatisPlusApplicationTests {
    @Autowired
    private UserMapper userMapper;

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

测试结果:

为了观察sql,我们加入以下配置到application.properties

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

此时再运行,控制台就可打印sql了


2、MybatisPlus的CRUD

目前,我们的user表中的字段如下,值得注意的是表的id并不是自增的?

1.插入操作-主键生成策略

执行如下代码,会发现很有意思的

现象:我们在添加user的时候并没有设置id,且数据库的id也不是自增的,但是最后一行的user对象中id却有输出

    @Test
    public void testInsert(){
        User user = new User();
        user.setName("谷小姐");
        user.setAge(18);
        user.setEmail("6665559999@qq.com");

        int result = userMapper.insert(user);
        System.out.println(result); //影响的行数
        System.out.println(user); //id自动回填
    }

控制台打印如下:

是因为mybatisplus默认实现自动回填id,这个id的生成策略又是什么呢


主键生成策略:

可以通过@TableId注解的 type属性来设置主键id的生成策略

默认使用如下:

@TableId(type = IdType.ASSIGN_ID)
private Long id;

(1)ASSIGN_ID(雪花算法)

? ??? ??如果不设置类型值,默认则使用IdType.ASSIGN_ID策略(自3.3.0起)。该策略会使用雪花算法自动生成主键ID,主键类型为长整型或字符串(分别对应的MySQL的表字段为BIGINT和VARCHAR),确保分布式系统的一个唯一id值

(2)ASSIGN_UUID(排除中划线的UUID)

? ??? ??如果使用IdType.ASSIGN_UUID策略,并重新自动生成排除中划线?的UUID作为主键。主键类型为String,对应MySQL字段为VARCHAR(32),包含(-)的话UUID是36长度的,(-)占了4个。

(3)AUTO(数据库ID自增)

? ??? ??对于像MySQL这样的支持主键自动递增的数据库,我们可以使用IdType.AUTO策略。 但是要求数据库字段是整形

(4)INPUT(插入前自行设置主键值)

(5)NONE(无状态)

? ??? ??如果使用IdType.NONE策略,表示未设置主键类型,使用默认的规则

------------------------

补充:

雪花算法(SnowFlake)是 Twitter 开源的分布式 id 生成算法,在分布式环境下产生不重复的id。使用一个 64 bit 的 long 型的数字作为全局唯一 id。
公式: 0 (最高位预留 1位) + 时间戳 (41 位) + 机器 ID (10 位) + 随机序列 (12 位) = 64 bit (long类型的值,最长19个数,例如1545580694141997057)


2.?更新操作-自动填充-版本号修改

现象:根据id修改名字的时候,只传了id和名字,拼的是动态sql,只修改名字,并不是完全的覆盖。

    @Test
    public void testUpdateById(){
        
        User user = new User();
        user.setId(1553211962987388930L);
        user.setAge(30);
        //UPDATE user SET age=? WHERE id=? 
        int result = userMapper.updateById(user);
        System.out.println(result);
    }

自动填充

项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。

我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作:

1.在数据库表user表添加datetime类型的新字段create_time、update_time,在实体类也添加对应的属性,命名格式:驼峰命名

import java.util.Date;
@Data
public class User {
    ......
        //添加
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    //@TableField(fill = FieldFill.UPDATE)
    //添加修改
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

2.在实体类上对应的属性上添加注解 配置自动填充

3.实现元对象处理器接口

MyMetaObjectHandler是随便起的名字,要注意加@Component注解

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import java.util.Date;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        //写实体类属性名
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}

测试添加功能时自动填充:

    @Test
    public void testInsert(){
        User user = new User();
        user.setName("悠米");
        user.setAge(19);
        user.setEmail("ym_888@qq.com");
        int result = userMapper.insert(user);
    }

打印的sql日志

数据库变化

测试修改功能的自动填充

    @Test
    public void testUpdateById(){
        User user = new User();
        user.setId(1553547529604321282L);
        user.setAge(24);
        int result = userMapper.updateById(user);
    }

打印sql日志

数据库变化?????


乐观锁-版本号修改

当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新。

乐观锁:在高并发的情况下保证数据的安全

1.数据库表user添加字段version【加默认值0或者使用@TableField,这里使用默认值】

?2.实体类加字段,字段上加注解@Version

    @Version
    private Integer version;

3.配置乐观锁的插件

在 MybatisPlusConfig(自定义配置类) 中注册 OptimisticLockerInterceptor 锁的拦截器,?也可以直接在启动类配置乐观锁的插件。我们选择在配置类中加入乐观锁的插件

@SpringBootConfiguration
public class MybatisPlusConfig {

    /**
     * 乐观锁插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}

在测试类得这么测试,不要像上面那样直接new一个user,然后修改。一定要先去查询

    @Test
    public void testUpdateById(){
        //查询
        User user = userMapper.selectById(1553554443532869633L);
        //修改数据
        user.setName("Helen Yao");
        user.setEmail("helen@qq.com");
        //执行更新
        userMapper.updateById(user);
    }

?实现方式

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

看源码可知: Long或者int,版本号则加1? ; 时间类型则返回当前时间


3.查询(id查询、批量查询、条件查询、分页查询)

3.1 id查询

    @Test
    public void testSelectById(){
        //根据id查询记录
        User user = userMapper.selectById(1L);
        System.out.println(user);
    }

?3.2 多个id批量查询

    @Test
    public void testSelectBatchIds(){
        //通过多个id批量查询
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
        //java的写法要会
        users.forEach(System.out::println);
    }

?3.3 map条件查询

通过map封装查询条件

注意:map中的key对应的是数据库中的列名。例如数据库user_id,实体类是userId,这时map的key需要填写user_id

    @Test
    public void testSelectByMap(){

        HashMap<String, Object> map = new HashMap<>();
        // 列名
        map.put("name", "悠米");
        map.put("age", 28);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }

3.4 Page?分页查询

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

在MybatisPlusConfig配置类中加入分页插件配置,也可以写在启动类

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

测试:最终通过page对象获取相关数据

查询第一页,每页5条数据

    @Test
    public void testSelectPage() {
        Page<User> page = new Page<>(1,5);
        //第二个参数表示查询条件,null表示查询所有
        userMapper.selectPage(page, null);
        page.getRecords().forEach(System.out::println);
    }

limit m,n? ? ? ? ? m:从第几条开始? ?n:查询多少条

page对象?里还有很多关于分页的信息,列如:

    System.out.println(page.getCurrent());//当前第几页
    System.out.println(page.getPages());//总页数
    System.out.println(page.getSize());//每页显示数量
    System.out.println(page.getTotal());//总记录数
    System.out.println(page.hasNext());//是否有下一页
    System.out.println(page.hasPrevious());//是否有上一页

4.删除(id删除、批量删除、条件删除、逻辑删除)

4.1 id删除

    @Test
    public void testDeleteById(){
        //根据id删除 【物理删除】
        int result = userMapper.deleteById(1L);
        System.out.println(result);
    }

?4.2 多个id批量删除

    @Test
    public void testDeleteBatchIds() {
        //多个id批量删除
        int result = userMapper.deleteBatchIds(Arrays.asList(3, 4, 5));
        System.out.println(result);
    }

?4.3 条件查询删除

    @Test
    public void testDeleteByMap() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "Helen");
        map.put("age", 18);
        //简单的条件查询删除
        int result = userMapper.deleteByMap(map);
        System.out.println(result);
    }

4.4 逻辑删除

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

1、数据库表user中添加字段deleted(或者is_deleted)

2、实体类添加deleted?字段和@TableLogic 注解

    @TableLogic
    private Integer deleted;

3、application.properties?配置是否被删除的逻辑值

此为默认值,如果你的默认值和mp默认的一样,该配置可无。

mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

测试逻辑删除

    /**
     * 测试 逻辑删除
     */
    @Test
    public void testLogicDelete() {
        int result = userMapper.deleteById(2L);
        System.out.println(result);
    }

注意:被删除数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作

此时再去查询该条数据

    @Test
    public void testSelectById(){
        User user = userMapper.selectById(2L);
        System.out.println(user);
    }


3、MybatisPlus的条件构造器

拼接各种条件(查询条件、删除条件、修改条件


QueryWrapper

注意:以下条件构造器的方法入参中的?column?均表示数据库字段

1、ge、gt、le、lt、isNull、isNotNull

    @Test
    public void testSelect() {

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //年龄大于等于25岁的
        queryWrapper.ge("age", 25);
        List<User> users = userMapper.selectList(queryWrapper);
        //int delete = userMapper.delete(queryWrapper);
        System.out.println(users);
    }

2、eq、ne

ne 不等于

    @Test
    public void testSelectOne() {

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", "飘絮");
        //seletOne返回的是一条实体记录,当出现多条时会报错
        User user = userMapper.selectOne(queryWrapper);
        System.out.println(user);
    }

3、between、notBetween

    @Test
    public void testSelectCount() {

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //between 包含大小边界
        queryWrapper.between("age", 20, 30);

        Integer count = userMapper.selectCount(queryWrapper);
        System.out.println(count);
    }

4、like、notLike、likeLeft、likeRight

    @Test
    public void testLike(){

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//        userQueryWrapper.like("name","d");//  %d%
//        userQueryWrapper.likeLeft("name","d"); //%d
        userQueryWrapper.likeRight("name","米"); // d%

        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println(users);
    }

5、orderBy、orderByDesc、orderByAsc

    @Test
    public void testSelectListOrderBy() {

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("age");

        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

6、last

    @Test
    public void testSelectListLast() {

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //直接拼接到 sql 的最后,只能调用一次,多次调用以最后一次为准
        queryWrapper.last("limit 3");
        //sql注入的风险:永远为真的条件
        //queryWrapper.last(" or 1=1");

        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

???????

7、指定要查询的列

    @Test
    public void testSelectListColumn() {

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        // select 限制返回的字段
        queryWrapper.select("id", "name", "age");
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:29:56  更:2022-08-06 10:34:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:16:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码