Java:MybatisPlus--高级

一、分页

1、分页插件

分页的本质就是需要设置一个拦截器,通过拦截器拦截了 SQL,通过在 SQL 语句的结尾添加 limit 关键字,来实现分页的效果。

2、通过配置类来指定一个具体数据库的分页插件

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
    }
}

3、分页查询的实现

@Test
void selectPage(){
    //1.创建 QueryWrapper 对象
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //2.创建分页查询对象,指定当前页和每页显示条数
    IPage<User> page = new Page<>(1,2;
    //3.执行分页查询
    userMapper.selectPage(page, lambdaQueryWrapper);
    //4.查看分页查询的结果
    System.out.println("当前页码值:"+page.getCurrent());
    System.out.println("每页显示数:"+page.getSize());
    System.out.println("总页数:"+page.getPages());
    System.out.println("总条数:"+page.getTotal());
    System.out.println("当前页数据:"+page.getRecords());
}

二、自定义分页

1、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.islunatic.mapper.UserMapper">
    <select id="selectByName" resultType="com.islunatic.pojo.User">
        select * from user where name = #{name}
    </select>
</mapper>

2、Mapper 接口中提供对应的方法,方法中将 IPage 对象作为参数传入

@Mapper
public interface UserMapper extends BaseMapper<User> {
    IPage<User> selectByName(IPage<User> page, String name);
}

三、ActiveRecord 模式

AR是一种领域模型模式,

特点:

是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User extends Model<User> {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

Model 类中提供了一些增删改查方法,可以直接使用实体类对象调用这增删改查方法,简化了操作的语法,但是底层是需要UserMapper的,所以持久层接口不能省略。 

具体使用方式

@Test
void activeRecordAdd(){
    User user = new User();
    user.setName("wang");
    user.setAge(35);
    user.setEmail("123456789@qq.com");
    user.insert();
}

@Test
void activeRecordDelete(){
    User user = new User();
    user.setId(8L);
    user.deleteById();
}

@Test
void activeRecordUpdate(){
    User user = new User();
    user.setId(6L);
    user.setAge(50);
    user.updateById();
}

@Test
void activeRecordSelect(){
    User user = new User();
    user.setId(1L);
    User user1= user.selectById();
    System.out.println(user1);
}

四、SimpleQuery

SimpleQuery可以对selectList查询后的结果用 Stream流进行了一些封装,可以返回一些指定果

1、list

①基于字段封装集合
@Test
void testList1(){
    List<Long> ids = SimpleQuery.list(newLambdaQueryWrapper<User>().eq(User::getName,         "Mary"), User::getId);
    System.out.println(ids);
}

 ②对于封装后的字段进行 lambda 操作

@Test
void testList2(){
    List<String> names = SimpleQuery.list(new
    LambdaQueryWrapper<User>().eq(User::getName, "Mary"),User::getName,e ->
    Optional.of(e.getName()).map(String::toLowerCase).ifPresent(e::setName));
    System.out.println(names);
}

 2、map

将所有的对象以 id, 实体的方式封装为 Map 集合
@Test
void testMap(){
    //将所有元素封装为 Map 形式
    Map<Long, User> Map1 = SimpleQuery.keyMap(new LambdaQueryWrapper<>(), User::getId);
    System.out.println(Map1 );
}

3、group

分组效果

@Test
void testGroup(){
    Map<String, List<User>> maps = SimpleQuery.group(new
    LambdaQueryWrapper<>(), User::getName);
    System.out.println(maps );
}

五、锁

常见的数据库锁类型有两种,悲观锁和乐观锁。

一次完成的修改操作是,先查询数据,然后修改数据。

1、悲观锁

悲观锁是在查询的时候就锁定数据,在这次请求未完成之前,不会释放锁。等到 这次请求完毕以后,再释放锁,释放了锁以后,其他请求才可以对于这条数据完成读写。

这样做的操作能够保证读取到的信息就是当前的信息,保证了信息的正确性,但是并发效率很低,在实际开发中使用悲观锁的场景很少,因为在并发时我们是要保证效率。

2、乐观锁

乐观锁是通过表字段完成设计的,他的核心思想是在读取的时候不加锁,其他请求依然可以读取到这个数据,在修改的时候判断一个数据是否有被修改过,如果有被修改过, 那本次请求的修改操作失效。

Update 表 set 字段 = 新值,version = version + 1 where version = 1

这样做的操作是不会对于数据读取产生影响,并发的效率较高。但是可能目前看到的数据并不是真实信息数据,是被修改之前的,但是在很多场景下是可以容忍的,并不是产生很大影响,例如很多时候我们看到的是有库存,或者都加入到购物车了,但是点进去以后库存没有了。

在实体类字段上,添加对应的属性,并使用@Version 标注为这是一个乐观锁字段信息。

通过配置拦截器,对每条修改语句完成语句的增强,让每条修改的sql语句在执行的时候,都加版本控制的功能。

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}
}

六、代码生成器

1、导入依赖

<!--代码生成器依赖-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.3</version>
</dependency>
<!--freemarker 模板依赖-->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>

2、编写代码生成器

@SpringBootTest
public class GeneratorApplicationTests {
    public static void main(String[] args) {
    FastAutoGenerator.create("jdbc:mysql://localhost:3306/mp?serverTimezone=UTC&cha
    racterEncoding=utf8&useUnicode=true&useSSL=false", "root", "root")
.globalConfig(builder -> {
        builder.author("phb") // 设置作者
            //.enableSwagger() // 开启 swagger 模式
            .fileOverride() // 覆盖已生成文件
            .outputDir("D://"); // 指定输出目录
        })
        .packageConfig(builder -> {
            builder.parent("com.islunatic") // 设置父包名
                .moduleName("mp") // 设置父包模块名
                //设置 mapperXml 生成路径
                .pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); 
        })
        .strategyConfig(builder -> {
            builder.addInclude("user") // 设置需要生成的表名
                .addTablePrefix(""); // 设置过滤表前缀
        })
        .templateEngine(new FreemarkerTemplateEngine()) // 使用 Freemarker 引擎模板,
默认的是 Velocity 引擎模板
            .execute();
    }
}

七、配置多数据源

1、导入依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.1.0</version>
</dependency>

2、编写数据源信息

spring:
  datasource:
      dynamic:
        primary: master
        strict: false
        datasource:
          master:
            username: root
            password: root
            url:jdbc:mysql://localhost:3306/mp?serverTimezone=UTC
            driver-class-name: com.mysql.cj.jdbc.Driver
          slave_1:
            username: root
            password: root
            url:jdbc:mysql://localhost:3306/mp2?serverTimezone=UTC
            driver-class-name: com.mysql.cj.jdbc.Driver

3、@DS注解描述不同的数据源信息

八、自动填充

1、在需要自动填充的实现类字段上添加注解

@TableField(fill = FieldFill.INSERT)
    private Long createUser;

@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;

2、自定义实现类

package com.islunatic.common;

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

import java.time.LocalDateTime;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        metaObject.setValue("createTime",LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("createUser",BaseContext.getCurrentId());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }
}

MetaObjectHandler提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null则不填充

字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus要预留注入SQL字段

填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component@Bean注入

3、工具类,设置自动填充创建用户的名称

package com.islunatic.common;

/**
 * 基于ThreadLocal封装工具类,用户保存和获取当前登录用户id
 */
public class BaseContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    //设置值
    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }
    //获取值
    public static Long getCurrentId(){
        return threadLocal.get();
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IsLuNaTiC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值