需求分析
在系统内需要将某些员工的信息作出个性化处理,且不能修改原表的数据。
例如在 B 表中将 “张三” 划分到产品设计部(在A表中为产品运营),在查询 “张三” 的数据之前,先到 B 表查询,如果存在数据则不再去 A 表查询。
思路分析
- A 表为原表,再克隆出相同结构的 B 表 ,在 B 表中作出个性化处理。
- 既然 A、B 表的结构相同,那么可以复用 B 表的 QueryWrapper 条件来实现查询结果的一致性,虽然两个表的字段相同,但在 Java 中是两个独立的 model 对象,不能直接使用 B 表的 QueryWrapper 去查询 A 表的数据。
- 目前的思路是通过 Java 反射的特性将 A 表的 QueryWrapper 对象条件复制到 B 表的 QueryWrapper,再对 B 表进行查询。
实现过程
在程序执行的过程中,观察 QueryWrapper
对象的属性我们可以发现,在执行一系列 .eq()
等条件配置后写入的参数值会体现在 expression
属性的中
可以根据一定的规律从 expression
属性来拼接出 where
后的 sql 条件,但取值的方式需要兼容各种情况的出现,比较繁琐。
由于 QueryWrapper 又继承于 AbstractWrapper
,从 AbstractWrapper 提供了一个 getSqlSegment 方法可以得到拼接后的 where 条件。
所以我们调用 queryWrapper.getSqlSegment() 会得到一个拼接后的 sql 子句,如下图
Mybatis Plus
将参数具体的值使用 #{ew.paramNameValuePairs.XXX}
进行转义,再进行最终的 sql 语句拼接时会将其转换为具体的参数值,而参数的值则存放在 paramNameValuePairs
这个 Map
属性中
到这里我们可以整理下思路:
-
将 A 表 QueryWrapper 对象的
paramNameValuePairs
和expression
属性赋给 B 表的 QueryWrapper 。 -
但是由于
QueryWrapper
类大部分属性都是私有的,并且只对外开放了 get 方法,所以我们需要通过反射来获取私有属性的值。
0x01:所以我们先定义一个方法,将任意对象的属性设置为特定的值
/**
* @author: Cory Lin
* @description 常用工具类
* @date: 2021/8/18 12:13 下午
*/
public class CommonUtil {
public static void setProperty(Object obj,String propertyName,Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
Class c = obj.getClass()