• Mybatis Plus 公共字段自动填充功能


    目录

     

    1、问题引入

    2、 基本功能实现

    3、功能完善

    3.1 ThreadLocal

    3.1.1 介绍

    3.1.2 常用方法

    3.2 思路分析

    3.3 代码实现


    1、问题引入

    在我们的项目开发中,我们会发现有一些数据库表字段是每个表都有的,例如 : 创建时间,创建人 ,更新时间,更新人。

    而我们目前的针对这些字段我们的目前的处理方式就是 增加或者修改的时候一个一个的去赋值。

    5674d081b3db678b957db8d1ee6e0fb6.png

    如果都按照上面的方法进行操作的话,那我们就需要在每个业务方法中进行操作,这样会不会显得我们的代码过于冗余、繁琐。

    这个时候我们就可以使用Mybatis Plus提供的公共字段自动填充功能。

    2、 基本功能实现

    Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。

    在上述的问题分析中,我们提到有四个公共字段,需要在新增/更新中进行赋值操作, 具体情况如下:

    字段名

    赋值时机

    说明

    createTime

    插入(INSERT)

    当前时间

    updateTime

    插入(INSERT) , 更新(UPDATE)

    当前时间

    createUser

    插入(INSERT)

    当前登录用户ID

    updateUser

    插入(INSERT) , 更新(UPDATE)

    当前登录用户ID

    接下来我们就开始编写代码。

    首先第一步就是在实体类的属性上加入 @TableField 注解,指定自动填充的策略。

    注 :

    fill : 字段自动填充策略

    添加好注解后,我们就需要按照框架要求编写元数据对象处理器这样的一个类,在此类中统一为公共字段赋值,注意!此类需要实现MetaObjectHandler接口。

    创建好类,我们就可以开始编写操作代码了。

    3、功能完善

    细心的朋友已经发现,我们上面只填充了时间,并没有填充创建人和更新人,现在我们就来完善一下。

    本来我想的是,我登录的时候是将用户id存入了HttpSession中,现在我从HttpSession中获取不就行了?

    但是 ,MyMetaObjectHandler类中是不能直接获得HttpSession对象的,所以我们需要通过其他方式来获取登录用户id。

    这里我们使用JAVA 给我们提供的一个类,ThreadLocal

    在了解 ThreadLocal 之前我们先了解当我们在增加/修改员工信息时, 我目前项目业务的执行流程是什么样子的,如下图:

    客户端发送的每次http请求,对应的在服务端都会分配一个新的线程来处理,在处理过程中涉及到下面类中的方法都属于相同的一个线程:

    • LoginCheckFilter (登录过滤器) 的doFilter方法
    • Controller的方法
    • MyMetaObjectHandler的insertFill/updateFill方法

    我们可以在上述类的方法中加入如下代码(获取当前线程ID,并输出):

    1. long id = Thread.currentThread().getId();
    2. log.info("线程id为:{}",id);

    执行功能进行验证,通过观察控制台输出可以发现,一次请求对应的线程id是相同的。

    3.1 ThreadLocal

    3.1.1 介绍

    ThreadLocal并不是一个Thread,而是Thread的局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

    ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问当前线程对应的值。

    3.1.2 常用方法

    public void set(T value)

    设置当前线程的线程局部变量的值

    public T get()

    返回当前线程所对应的线程局部变量的值

    public void remove()

    删除当前线程所对应的线程局部变量的值

    3.2 思路分析

    1. 我们可以先在LoginCheckFilter(登录过滤器) doFilter方法中获取当前登录用户id。并调用ThreadLocalset方法来设置当前线程的线程局部变量的值(用户id)。
    2. MyMetaObjectHandlerinsertFill/updateFill方法中调用ThreadLocalget方法来获得当前线程所对应的线程局部变量的值(用户id)。
    3. 如果在后续的操作中, 我们需要在Controller / Service中要使用当前登录用户的ID, 可以直接从ThreadLocal直接获取。

    3.3 代码实现

    首先为了使用方便,我们可以编写一个基于ThreadLocal封装的工具类,主要get 和 set 方法。

    1. /**
    2. * @description: 基于ThreadLocal封装工具类,用户保存和获取当前登录用户id
    3. * @author: Jie
    4. * @date: 2022/8/12 14:18
    5. **/
    6. public class BaseContext {
    7. private static ThreadLocal threadLocal = new ThreadLocal<>();
    8. /**
    9. * @description: 设置值
    10. * @author: Jie
    11. * @date: 2022/8/12 14:18
    12. * @param: [id] 线程id
    13. **/
    14. public static void setCurrentId(Long id){
    15. threadLocal.set(id);
    16. }
    17. /**
    18. * @description: 获取值
    19. * @author: Jie
    20. * @date: 2022/8/12 14:18
    21. **/
    22. public static Long getCurrentId(){
    23. return threadLocal.get();
    24. }
    25. }

    然后在LoginCheckFilter(登录过滤器)的doFilter方法中调用BaseContext来设置当前登录用户的id。

    接下来我们就可以 在MyMetaObjectHandler的方法中调用BaseContext获取登录用户的id。

  • 相关阅读:
    行为型:策略模式
    分享一个基于uniapp+springboot技术开发的校园失物招领小程序(源码、lw、调试)
    VR全景营销颠覆传统营销,让消费者身临其境
    ELK——Elasticsearch(一)
    STM32——触摸屏实验-电阻型触摸屏-M4
    网上PHP+Redis分布式锁的实现都有问题
    JetPack架构组件之ViewModel和Livedata使用
    vivado产生报告阅读分析6-时序报告2
    语言模型编码中/英文句子格式详解
    性能测试 - 理论
  • 原文地址:https://blog.csdn.net/weixin_53041251/article/details/126895816