【教程】 MyBatis-Plus 多表联查 MyBatis-Plus-Join
MyBatis-Plus-Join ()
MyBatis-Plus-Join (opens new window)(简称 MPJ)是一个 MyBatis-Plus (opens new window)的增强工具,在 MyBatis-Plus 的基础上只做增强不做改变,为简化开发、提高效率而生。
#特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 无感引入, 支持MP风格的查询, 您会MP就会MPJ, 无需额外的学习成本
- 兼容MP的别名、逻辑删除、枚举列、TypeHandle列等特性
- 支持注解形式一对一、一对多和连表查询形式的一对一和一对多
使用方法示例 1. 修改mapper
public interface UserMapper extends BaseMapper<User> {
}
修改为
public interface UserMapper extends MPJBaseMapper<User> {
}
2. 添加联查表
//组装条件
//MPJQueryWrapper<User> queryWrapper = (user, ());
MPJQueryWrapper<User> queryWrapper = new MPJQueryWrapper();
Page<User> page = new Page<User>(pageNo, pageSize);
//添加联查表
("sys_user_ext q on q.user_id = ");
IPage<User> pageList = (page, queryWrapper);
3. 服务层查询
public IPage<User> pageJoin(Page<User> page, MPJQueryWrapper<User> queryWrapper) {
//配置需要查询的字段
();
// ("");
return (page, , queryWrapper);
}
4. 请求体
@Data
@ApiModel(description = "请求体")
public class UserListReq extends User {
//联查表的字段 需要加别名 不加别名的话 默认是主表 也就是 t.
@TableField("")
@ApiModelProperty(value = "用户地址")
private String addr;
}
可以不用这个
JoinQueryGenerator
package ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .*;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .*;
import ;
import ;
import ;
/**
* @Description: 查询生成器
* @author: jeecg-boot
*/
@Slf4j
public class JoinQueryGenerator {
public static final String SQL_RULES_COLUMN = "SQL_RULES_COLUMN";
private static final String BEGIN = "_begin";
private static final String END = "_end";
/**
* 数字类型字段,拼接此后缀 接受多值参数
*/
private static final String MULTI = "_MultiString";
private static final String STAR = "*";
private static final String COMMA = ",";
/**
* 查询 逗号转义符 相当于一个逗号【作废】
*/
public static final String QUERY_COMMA_ESCAPE = "++";
private static final String NOT_EQUAL = "!";
/**页面带有规则值查询,空格作为分隔符*/
private static final String QUERY_SEPARATE_KEYWORD = " ";
/**高级查询前端传来的参数名*/
private static final String SUPER_QUERY_PARAMS = "superQueryParams";
/** 高级查询前端传来的拼接方式参数名 */
private static final String SUPER_QUERY_MATCH_TYPE = "superQueryMatchType";
/** 单引号 */
public static final String SQL_SQ = "'";
/**排序列*/
private static final String ORDER_COLUMN = "column";
/**排序方式*/
private static final String ORDER_TYPE = "order";
private static final String ORDER_TYPE_ASC = "ASC";
/**mysql 模糊查询之特殊字符下划线 (_、\)*/
public static final String LIKE_MYSQL_SPECIAL_STRS = "_,%";
/**日期格式化yyyy-MM-dd*/
public static final String YYYY_MM_DD = "yyyy-MM-dd";
/**to_date*/
public static final String TO_DATE = "to_date";
/**时间格式化 */
private static final ThreadLocal<SimpleDateFormat> LOCAL = new ThreadLocal<SimpleDateFormat>();
private static SimpleDateFormat getTime(){
SimpleDateFormat time = ();
if(time == null){
time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
(time);
}
return time;
}
/**
* 获取查询条件构造器QueryWrapper实例 通用查询条件已被封装完成
* @param searchObj 查询实体
* @param parameterMap ()
* @return QueryWrapper实例
*/
public static <T> MPJQueryWrapper<T> initQueryWrapper(T searchObj, Map<String, String[]> parameterMap){
long start = ();
MPJQueryWrapper<T> queryWrapper = new MPJQueryWrapper<T>();
installMplus(queryWrapper, searchObj, parameterMap, null);
("---查询条件构造器初始化完成,耗时:"+(()-start)+"毫秒----");
return queryWrapper;
}
//update-begin---author:chenrui ---date:20240527 for:[TV360X-378]增加自定义字段查询规则功能------------
/**
* 获取查询条件构造器QueryWrapper实例 通用查询条件已被封装完成
* @param searchObj 查询实体
* @param parameterMap ()
* @param customRuleMap 自定义字段查询规则 {field:QueryRuleEnum}
* @return QueryWrapper实例
*/
public static <T> MPJQueryWrapper<T> initQueryWrapper(T searchObj,Map<String, String[]> parameterMap, Map<String, QueryRuleEnum> customRuleMap){
long start = ();
MPJQueryWrapper<T> queryWrapper = new MPJQueryWrapper<T>();
installMplus(queryWrapper, searchObj, parameterMap, customRuleMap);
("---查询条件构造器初始化完成,耗时:"+(()-start)+"毫秒----");
return queryWrapper;
}
//update-end---author:chenrui ---date:20240527 for:[TV360X-378]增加自定义字段查询规则功能------------
/**
* 组装Mybatis Plus 查询条件
* <p>使用此方法 需要有如下几点注意:
* <br>1.使用QueryWrapper 而非LambdaQueryWrapper;
* <br>2.实例化QueryWrapper时不可将实体传入参数
* <br>错误示例:如QueryWrapper<JeecgDemo> queryWrapper = new QueryWrapper<JeecgDemo>(jeecgDemo);
* <br>正确示例:QueryWrapper<JeecgDemo> queryWrapper = new QueryWrapper<JeecgDemo>();
* <br>3.也可以不使用这个方法直接调用 {@link #initQueryWrapper}直接获取实例
*/
private static void installMplus(MPJQueryWrapper<?> queryWrapper, Object searchObj, Map<String, String[]> parameterMap, Map<String, QueryRuleEnum> customRuleMap) {
/*
* 注意:权限查询由前端配置数据规则 当一个人有多个所属部门时候 可以在规则配置包含条件 orgCode 包含 #{sys_org_code}
但是不支持在自定义SQL中写orgCode in #{sys_org_code}
当一个人只有一个部门 就直接配置等于条件: orgCode 等于 #{sys_org_code} 或者配置自定义SQL: orgCode = '#{sys_org_code}'
*/
//区间条件组装 模糊查询 高级查询组装 简单排序 权限查询
PropertyDescriptor[] origDescriptors = (searchObj);
Map<String,SysPermissionDataRuleModel> ruleMap = getRuleMap();
Map<String, Field> fieldMap = new HashMap<>();
Field[] declaredFields = ().getDeclaredFields();
for (Field declaredField : declaredFields) {
((), declaredField);
}
//权限规则自定义SQL表达式
for (String c : ()) {
if((c) && (SQL_RULES_COLUMN)){
(i ->(getSqlRuleValue((c).getRuleValue())));
}
}
String name, type, column;
// update-begin--Author:taoyan Date:20200923 for:issues/1671 如果字段加注解了@TableField(exist = false),不走DB查询-------
//定义实体字段和数据库字段名称的映射 高级查询中 只能获取实体字段 如果设置TableField注解 那么查询条件会出问题
Map<String,String> fieldColumnMap = new HashMap<>(5);
for (int i = 0; i < ; i++) {
//aliasName = origDescriptors[i].getName(); mybatis 不存在实体属性 不用处理别名的情况
name = origDescriptors[i].getName();
// Field field1 = (name);
// TableField annotationTableField = ();
// if(annotationTableField != null){
// String value = ();
// }
type = origDescriptors[i].getPropertyType().toString();
try {
if (judgedIsUselessField(name)|| !(searchObj, name)) {
continue;
}
Object value = (searchObj, name);
column = ((), name);
if(column==null){
//column为null只有一种情况 那就是 添加了注解@TableField(exist = false) 后续都不用处理了
continue;
}
(name,column);
//数据权限查询
if((name)) {
addRuleToQueryWrapper((name), column, origDescriptors[i].getPropertyType(), queryWrapper);
}
//区间查询
doIntervalQuery(queryWrapper, parameterMap, type, name, column);
//判断单值 参数带不同标识字符串 走不同的查询
//TODO 这种前后带逗号的支持分割后模糊查询(多选字段查询生效) 示例:,1,3,
if (null != value && ().startsWith(COMMA) && ().endsWith(COMMA)) {
String multiLikeval = ().replace(",,", COMMA);
String[] vals = (1, ()).split(COMMA);
final String field = (column);
if(>1) {
(j -> {
("---查询过滤器,Query规则---field:{}, rule:{}, value:{}", field, "like", vals[0]);
j = (field,vals[0]);
for (int k=1;k<;k++) {
j = ().like(field,vals[k]);
("---查询过滤器,Query规则 .or()---field:{}, rule:{}, value:{}", field, "like", vals[k]);
}
//return j;
});
}else {
("---查询过滤器,Query规则---field:{}, rule:{}, value:{}", field, "like", vals[0]);
(j -> (field,vals[0]));
}
}else {
//update-begin---author:chenrui ---date:20240527 for:[TV360X-378]增加自定义字段查询规则功能------------
QueryRuleEnum rule;
if(null != customRuleMap && (name)) {
// 有自定义规则,使用自定义规则.
rule = (name);
}else {
//根据参数值带什么关键字符串判断走什么类型的查询
rule = convert2Rule(value);
}
//update-end---author:chenrui ---date:20240527 for:[TV360X-378]增加自定义字段查询规则功能------------
value = replaceValue(rule,value);
// add -begin 添加判断为字符串时设为全模糊查询
//if( (rule==null || (rule)) && "class ".equals(type)) {
// 可以设置左右模糊或全模糊,因人而异
//rule = ;
//}
// add -end 添加判断为字符串时设为全模糊查询
addEasyQuery(queryWrapper, column, rule, value);
}
} catch (Exception e) {
((), e);
}
}
// 排序逻辑 处理
doMultiFieldsOrder(queryWrapper, parameterMap, fieldColumnMap);
//高级查询
doSuperQuery(queryWrapper, parameterMap, fieldColumnMap);
// update-end--Author:taoyan Date:20200923 for:issues/1671 如果字段加注解了@TableField(exist = false),不走DB查询-------
}
/**
* 区间查询
* @param queryWrapper query对象
* @param parameterMap 参数map
* @param type 字段类型
* @param filedName 字段名称
* @param columnName 列名称
*/
private static void doIntervalQuery(MPJQueryWrapper<?> queryWrapper, Map<String, String[]> parameterMap, String type, String filedName, String columnName) throws ParseException {
// 添加 判断是否有区间值
String endValue = null,beginValue = null;
if (parameterMap != null && (filedName + BEGIN)) {
beginValue = (filedName + BEGIN)[0].trim();
addQueryByRule(queryWrapper, columnName, type, beginValue, );
}
if (parameterMap != null && (filedName + END)) {
endValue = (filedName + END)[0].trim();
addQueryByRule(queryWrapper, columnName, type, endValue, );
}
//多值查询
if (parameterMap != null && (filedName + MULTI)) {
endValue = (filedName + MULTI)[0].trim();
addQueryByRule(queryWrapper, (MULTI,""), type, endValue, );
}
}
private static void doMultiFieldsOrder(MPJQueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap, Map<String,String> fieldColumnMap) {
Set<String> allFields = ();
String column=null,order=null;
if(parameterMap!=null&& (ORDER_COLUMN)) {
column = (ORDER_COLUMN)[0];
}
if(parameterMap!=null&& (ORDER_TYPE)) {
order = (ORDER_TYPE)[0];
}
("排序规则>>列:" + column + ",排序方式:" + order);
//update-begin-author:scott date:2022-11-07 for:避免用户自定义表无默认字段{创建时间},导致排序报错
//TODO 避免用户自定义表无默认字段创建时间,导致排序报错
if(DataBaseConstant.CREATE_TIME.equals(column) && !(DataBaseConstant.CREATE_TIME)){
column = "id";
("检测到实体里没有字段createTime,改成采用ID排序!");
}
//update-end-author:scott date:2022-11-07 for:避免用户自定义表无默认字段{创建时间},导致排序报错
if ((column) && (order)) {
//字典字段,去掉字典翻译文本后缀
if((CommonConstant.DICT_TEXT_SUFFIX)) {
column = (0, (CommonConstant.DICT_TEXT_SUFFIX));
}
//update-begin-author:taoyan date:2022-5-16 for: issues/3676 获取系统用户列表时,使用SQL注入生效
//判断column是不是当前实体的
("当前字段有:"+ allFields);
if (!allColumnExist(column, allFields)) {
throw new JeecgBootException("请注意,将要排序的列字段不存在:" + column);
}
//update-end-author:taoyan date:2022-5-16 for: issues/3676 获取系统用户列表时,使用SQL注入生效
//update-begin-author:scott date:2022-10-10 for:【jeecg-boot/issues/I5FJU6】doMultiFieldsOrder() 多字段排序方法存在问题
//多字段排序方法没有读取 MybatisPlus 注解 @TableField 里 value 的值
if ((",")) {
List<String> columnList = ((","));
String columnStrNew = ().map(c -> (c)).collect((","));
if ((columnStrNew)) {
column = columnStrNew;
}
}else{
column = (column);
}
//update-end-author:scott date:2022-10-10 for:【jeecg-boot/issues/I5FJU6】doMultiFieldsOrder() 多字段排序方法存在问题
//SQL注入check
(column);
//update-begin--Author:scott Date:20210531 for:36 多条件排序无效问题修正-------
// 排序规则修改
// 将现有排序 _ 前端传递排序条件{....,column: 'column1,column2',order: 'desc'} 翻译成sql "column1,column2 desc"
// 修改为 _ 前端传递排序条件{....,column: 'column1,column2',order: 'desc'} 翻译成sql "column1 desc,column2 desc"
List<String> sqlInjectSortFields = ((","));
List fields = new ArrayList();
for (int i = 0; i < (); i++) {
String s = (i);
if((".")){
(s);
}else{
("t." + s);
}
}
if (().indexOf(ORDER_TYPE_ASC)>=0) {
(fields);
} else {
(fields);
}
//update-end--Author:scott Date:20210531 for:36 多条件排序无效问题修正-------
}
}
//update-begin-author:taoyan date:2022-5-23 for: issues/3676 获取系统用户列表时,使用SQL注入生效
/**
* 多字段排序 判断所传字段是否存在
* @return
*/
private static boolean allColumnExist(String columnStr, Set<String> allFields){
boolean exist = true;
if((COMMA)>=0){
String[] arr = (COMMA);
for(String column: arr){
if(!(column)){
exist = false;
break;
}
}
}else{
exist = (columnStr);
}
return exist;
}
//update-end-author:taoyan date:2022-5-23 for: issues/3676 获取系统用户列表时,使用SQL注入生效
/**
* 高级查询
* @param queryWrapper 查询对象
* @param parameterMap 参数对象
* @param fieldColumnMap 实体字段和数据库列对应的map
*/
private static void doSuperQuery(MPJQueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap, Map<String,String> fieldColumnMap) {
if(parameterMap!=null&& (SUPER_QUERY_PARAMS)){
String superQueryParams = (SUPER_QUERY_PARAMS)[0];
String superQueryMatchType = (SUPER_QUERY_MATCH_TYPE) != null ? (SUPER_QUERY_MATCH_TYPE)[0] : ();
MatchTypeEnum matchType = (superQueryMatchType);
// update-begin--Author:sunjianlei Date:20200325 for:高级查询的条件要用括号括起来,防止和用户的其他条件冲突 -------
try {
superQueryParams = (superQueryParams, "UTF-8");
List<QueryCondition> conditions = (superQueryParams, );
if (conditions == null || () == 0) {
return;
}
// update-begin-author:sunjianlei date:20220119 for: 【JTC-573】 过滤空条件查询,防止 sql 拼接多余的 and
List<QueryCondition> filterConditions = ().filter(
rule -> (())
&& (())
&& (())
).collect(());
if (() == 0) {
return;
}
// update-end-author:sunjianlei date:20220119 for: 【JTC-573】 过滤空条件查询,防止 sql 拼接多余的 and
("---高级查询参数-->" + filterConditions);
(andWrapper -> {
for (int i = 0; i < (); i++) {
QueryCondition rule = (i);
if ((())
&& (())
&& (())) {
("SuperQuery ==> " + ());
//update-begin-author:taoyan date:20201228 for: 【高级查询】 oracle 日期等于查询报错
Object queryValue = ();
if("date".equals(())){
queryValue = DateUtils.str2Date((),DateUtils.date_sdf.get());
}else if("datetime".equals(())){
queryValue = DateUtils.str2Date((), ());
}
// update-begin--author:sunjianlei date:20210702 for:【/issues/I3VR8E】高级查询没有类型转换,查询参数都是字符串类型 ----
String dbType = ();
if ((dbType)) {
try {
String valueStr = (queryValue);
switch (().trim()) {
case "int":
queryValue = (valueStr);
break;
case "bigdecimal":
queryValue = new BigDecimal(valueStr);
break;
case "short":
queryValue = (valueStr);
break;
case "long":
queryValue = (valueStr);
break;
case "float":
queryValue = (valueStr);
break;
case "double":
queryValue = (valueStr);
break;
case "boolean":
queryValue = (valueStr);
break;
default:
}
} catch (Exception e) {
("高级查询值转换失败:", e);
}
}
// update-begin--author:sunjianlei date:20210702 for:【/issues/I3VR8E】高级查询没有类型转换,查询参数都是字符串类型 ----
addEasyQuery(andWrapper, (()), (()), queryValue);
//update-end-author:taoyan date:20201228 for: 【高级查询】 oracle 日期等于查询报错
// 如果拼接方式是OR,就拼接OR
if ( == matchType && i < (() - 1)) {
();
}
}
}
//return andWrapper;
});
} catch (UnsupportedEncodingException e) {
("--高级查询参数转码失败:" + superQueryParams, e);
} catch (Exception e) {
("--高级查询拼接失败:" + ());
();
}
// update-end--Author:sunjianlei Date:20200325 for:高级查询的条件要用括号括起来,防止和用户的其他条件冲突 -------
}
//(" superQuery getCustomSqlSegment: "+ ());
}
/**
* 根据所传的值 转化成对应的比较方式
* 支持><= like in !
* @param value
* @return
*/
public static QueryRuleEnum convert2Rule(Object value) {
// 避免空数据
// update-begin-author:taoyan date:20210629 for: 查询条件输入空格导致return null后续判断导致抛出null异常
if (value == null) {
return ;
}
String val = (value + "").toString().trim();
if (() == 0) {
return ;
}
// update-end-author:taoyan date:20210629 for: 查询条件输入空格导致return null后续判断导致抛出null异常
QueryRuleEnum rule =null;
//update-begin--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------
//TODO 此处规则,只适用于 le lt ge gt
// step 2 .>= =<
int length2 = 2;
int length3 = 3;
if (rule == null && () >= length3) {
if(QUERY_SEPARATE_KEYWORD.equals((length2, length3))){
rule = ((0, 2));
}
}
// step 1 .> <
if (rule == null && () >= length2) {
if(QUERY_SEPARATE_KEYWORD.equals((1, length2))){
rule = ((0, 1));
}
}
//update-end--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284---------------------
// step 3 like
//update-begin-author:taoyan for: /issues/3382 默认带*就走模糊,但是如果只有一个*,那么走等于查询
if(rule == null && (STAR)){
rule = ;
}
//update-end-author:taoyan for: /issues/3382 默认带*就走模糊,但是如果只有一个*,那么走等于查询
if (rule == null && (STAR)) {
if ((STAR) && (STAR)) {
rule = ;
} else if ((STAR)) {
rule = QueryRuleEnum.LEFT_LIKE;
} else if((STAR)){
rule = QueryRuleEnum.RIGHT_LIKE;
}
}
// step 4 in
if (rule == null && (COMMA)) {
//TODO in 查询这里应该有个bug 如果一字段本身就是多选 此时用in查询 未必能查询出来
rule = ;
}
// step 5 !=
if(rule == null && (NOT_EQUAL)){
rule = ;
}
// step 6 xx+xx+xx 这种情况适用于如果想要用逗号作精确查询 但是系统默认逗号走in 所以可以用++替换【此逻辑作废】
if(rule == null && (QUERY_COMMA_ESCAPE)>0){
rule = QueryRuleEnum.EQ_WITH_ADD;
}
//update-begin--Author:taoyan Date:20201229 for:initQueryWrapper组装sql查询条件错误 #284---------------------
//特殊处理:Oracle的表达式to_date('xxx','yyyy-MM-dd')含有逗号,会被识别为in查询,转为等于查询
if(rule == && (YYYY_MM_DD)>=0 && (TO_DATE)>=0){
rule = ;
}
//update-end--Author:taoyan Date:20201229 for:initQueryWrapper组装sql查询条件错误 #284---------------------
return rule != null ? rule : ;
}
/**
* 替换掉关键字字符
*
* @param rule
* @param value
* @return
*/
private static Object replaceValue(QueryRuleEnum rule, Object value) {
if (rule == null) {
return null;
}
if (! (value instanceof String)){
return value;
}
String val = (value + "").toString().trim();
//update-begin-author:taoyan date:20220302 for: 查询条件的值为等号(=)bug #3443
if(().equals(val)){
return val;
}
//update-end-author:taoyan date:20220302 for: 查询条件的值为等号(=)bug #3443
if (rule == ) {
value = (1, () - 1);
//mysql 模糊查询之特殊字符下划线 (_、\)
value = specialStrConvert(());
} else if (rule == QueryRuleEnum.LEFT_LIKE || rule == ) {
value = (1);
//mysql 模糊查询之特殊字符下划线 (_、\)
value = specialStrConvert(());
} else if (rule == QueryRuleEnum.RIGHT_LIKE) {
value = (0, () - 1);
//mysql 模糊查询之特殊字符下划线 (_、\)
value = specialStrConvert(());
} else if (rule == ) {
value = (",");
} else if (rule == QueryRuleEnum.EQ_WITH_ADD) {
value = ("\\+\\+", COMMA);
}else {
//update-begin--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------
if((())){
//TODO 此处逻辑应该注释掉-> 如果查询内容中带有查询匹配规则符号,就会被截取的(比如:>=您好)
value = ((),"");
}else if((()+QUERY_SEPARATE_KEYWORD)){
value = (()+QUERY_SEPARATE_KEYWORD,"").trim();
}
//update-end--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------
}
return value;
}
private static void addQueryByRule(MPJQueryWrapper<?> queryWrapper,String name,String type,String value,QueryRuleEnum rule) throws ParseException {
if((value)) {
//update-begin--Author:sunjianlei Date:20220104 for:【JTC-409】修复逗号分割情况下没有转换类型,导致类型严格的数据库查询报错 -------------------
// 针对数字类型字段,多值查询
if((COMMA)){
Object[] temp = ((COMMA)).map(v -> {
try {
return (v, type, rule);
} catch (ParseException e) {
();
return v;
}
}).toArray();
addEasyQuery(queryWrapper, name, rule, temp);
return;
}
Object temp = (value, type, rule);
addEasyQuery(queryWrapper, name, rule, temp);
//update-end--Author:sunjianlei Date:20220104 for:【JTC-409】修复逗号分割情况下没有转换类型,导致类型严格的数据库查询报错 -------------------
}
}
/**
* 根据类型转换给定的值
* @param value
* @param type
* @param rule
* @return
* @throws ParseException
*/
private static Object parseByType(String value, String type, QueryRuleEnum rule) throws ParseException {
Object temp;
switch (type) {
case "class ":
temp = (value);
break;
case "class ":
temp = new BigDecimal(value);
break;
case "class ":
temp = (value);
break;
case "class ":
temp = (value);
break;
case "class ":
temp = (value);
break;
case "class ":
temp = (value);
break;
case "class ":
temp = getDateQueryByRule(value, rule);
break;
default:
temp = value;
break;
}
return temp;
}
/**
* 获取日期类型的值
* @param value
* @param rule
* @return
* @throws ParseException
*/
private static Date getDateQueryByRule(String value,QueryRuleEnum rule) throws ParseException {
Date date = null;
int length = 10;
if(()==length) {
if(rule==) {
//比较大于
date = getTime().parse(value + " 00:00:00");
}else if(rule==) {
//比较小于
date = getTime().parse(value + " 23:59:59");
}
//TODO 日期类型比较特殊 可能oracle下不一定好使
}
if(date==null) {
date = getTime().parse(value);
}
return date;
}
/**
* 根据规则走不同的查询
* @param queryWrapper QueryWrapper
* @param name 字段名字
* @param rule 查询规则
* @param value 查询条件值
*/
public static void addEasyQuery(MPJQueryWrapper<?> queryWrapper, String name, QueryRuleEnum rule, Object value) {
if (name==null || value == null || rule == null || (value)) {
return;
}
name = (name);
if(!(".")){
name = "t." + name;
}
("---高级查询 Query规则---field:{} , rule:{} , value:{}",name,(),value);
switch (rule) {
case GT:
(name, value);
break;
case GE:
(name, value);
break;
case LT:
(name, value);
break;
case LE:
(name, value);
break;
case EQ:
case EQ_WITH_ADD:
(name, value);
break;
case NE:
(name, value);
break;
case IN:
if(value instanceof String) {
(name, (Object[])().split(COMMA));
}else if(value instanceof String[]) {
(name, (Object[]) value);
}
//update-begin-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671
else if(().isArray()) {
(name, (Object[])value);
}else {
(name, value);
}
//update-end-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671
break;
case LIKE:
(name, value);
break;
case LEFT_LIKE:
(name, value);
break;
case NOT_LEFT_LIKE:
(name, value);
break;
case RIGHT_LIKE:
(name, value);
break;
case NOT_RIGHT_LIKE:
(name, value);
break;
//update-begin---author:chenrui ---date:20240527 for:[TV360X-378]下拉多框根据条件查询不出来:增加自定义字段查询规则功能------------
case LIKE_WITH_OR:
final String nameFinal = name;
Object[] vals;
if (value instanceof String) {
vals = ().split(COMMA);
} else if (value instanceof String[]) {
vals = (Object[]) value;
}
//update-begin-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671
else if (().isArray()) {
vals = (Object[]) value;
} else {
vals = new Object[]{value};
}
(j -> {
("---查询过滤器,Query规则---field:{}, rule:{}, value:{}", nameFinal, "like", vals[0]);
j = (nameFinal, vals[0]);
for (int k = 1; k < ; k++) {
j = ().like(nameFinal, vals[k]);
("---查询过滤器,Query规则 .or()---field:{}, rule:{}, value:{}", nameFinal, "like", vals[k]);
}
});
break;
//update-end---author:chenrui ---date:20240527 for:[TV360X-378]下拉多框根据条件查询不出来:增加自定义字段查询规则功能------------
default:
("--查询规则未匹配到---");
break;
}
}
/**
*
* @param name
* @return
*/
private static boolean judgedIsUselessField(String name) {
return "class".equals(name) || "ids".equals(name)
|| "page".equals(name) || "rows".equals(name)
|| "sort".equals(name) || "order".equals(name);
}
/**
* 获取请求对应的数据权限规则 TODO 相同列权限多个 有问题
* @return
*/
public static Map<String, SysPermissionDataRuleModel> getRuleMap() {
Map<String, SysPermissionDataRuleModel> ruleMap = new HashMap<>(5);
List<SysPermissionDataRuleModel> list = null;
//update-begin-author:taoyan date:2023-6-1 for:QQYUN-5441 【简流】获取多个用户/部门/角色 设置部门查询 报错
try {
list = ();
}catch (Exception e){
("根据request对象获取权限数据失败,可能是定时任务中执行的。", e);
}
//update-end-author:taoyan date:2023-6-1 for:QQYUN-5441 【简流】获取多个用户/部门/角色 设置部门查询 报错
if(list != null&&()>0){
if((0)==null){
return ruleMap;
}
for (SysPermissionDataRuleModel rule : list) {
String column = ();
if(QueryRuleEnum.SQL_RULES.getValue().equals(())) {
column = SQL_RULES_COLUMN+();
}
(column, rule);
}
}
return ruleMap;
}
private static void addRuleToQueryWrapper(SysPermissionDataRuleModel dataRule, String name, Class propertyType, MPJQueryWrapper<?> queryWrapper) {
QueryRuleEnum rule = (());
if(() && ! ()) {
String[] values = ().split(",");
Object[] objs = new Object[];
for (int i = 0; i < ; i++) {
objs[i] = (values[i], propertyType);
}
addEasyQuery(queryWrapper, name, rule, objs);
}else {
if (()) {
addEasyQuery(queryWrapper, name, rule, converRuleValue(()));
}else if (()) {
String dateStr =converRuleValue(());
int length = 10;
if(()==length){
addEasyQuery(queryWrapper, name, rule, DateUtils.str2Date(dateStr,DateUtils.date_sdf.get()));
}else{
addEasyQuery(queryWrapper, name, rule, DateUtils.str2Date(dateStr,()));
}
}else {
addEasyQuery(queryWrapper, name, rule, ((), propertyType));
}
}
}
public static String converRuleValue(String ruleValue) {
String value = (ruleValue,null);
return value!= null ? value : ruleValue;
}
/**
* @author: scott
* @Description: 去掉值前后单引号
* @date: 2020/3/19 21:26
* @param ruleValue:
* @Return:
*/
public static String trimSingleQuote(String ruleValue) {
if ((ruleValue)) {
return "";
}
if ((JoinQueryGenerator.SQL_SQ)) {
ruleValue = (1);
}
if ((JoinQueryGenerator.SQL_SQ)) {
ruleValue = (0, () - 1);
}
return ruleValue;
}
public static String getSqlRuleValue(String sqlRule){
try {
Set<String> varParams = getSqlRuleParams(sqlRule);
for(String var:varParams){
String tempValue = converRuleValue(var);
sqlRule = ("#{"+var+"}",tempValue);
}
} catch (Exception e) {
((), e);
}
return sqlRule;
}
/**
* 获取sql中的#{key} 这个key组成的set
*/
public static Set<String> getSqlRuleParams(String sql) {
if((sql)){
return null;
}
Set<String> varParams = new HashSet<String>();
String regex = "\\#\\{\\w+\\}";
Pattern p = (regex);
Matcher m = (sql);
while(()){
String var = ();
((("{")+1,("}")));
}
return varParams;
}
/**
* 获取查询条件
* @param field
* @param alias
* @param value
* @param isString
* @return
*/
public static String getSingleQueryConditionSql(String field,String alias,Object value,boolean isString) {
return (field, alias, value, isString,null);
}
/**
* 根据权限相关配置生成相关的SQL 语句
* @param clazz
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static String installAuthJdbc(Class<?> clazz) {
StringBuffer sb = new StringBuffer();
//权限查询
Map<String,SysPermissionDataRuleModel> ruleMap = getRuleMap();
PropertyDescriptor[] origDescriptors = (clazz);
String sqlAnd = " and ";
for (String c : ()) {
if((c) && (SQL_RULES_COLUMN)){
(sqlAnd+getSqlRuleValue((c).getRuleValue()));
}
}
String name, column;
for (int i = 0; i < ; i++) {
name = origDescriptors[i].getName();
if (judgedIsUselessField(name)) {
continue;
}
if((name)) {
column = (clazz, name);
if(column==null){
continue;
}
SysPermissionDataRuleModel dataRule = (name);
QueryRuleEnum rule = (());
Class propType = origDescriptors[i].getPropertyType();
boolean isString = ();
Object value;
//update-begin---author:chenrui ---date:20240527 for:[TV360X-539]数据权限,配置日期等于条件时后端报转换错误------------
if(isString || (propType)) {
//update-end---author:chenrui ---date:20240527 for:[TV360X-539]数据权限,配置日期等于条件时后端报转换错误------------
value = converRuleValue(());
}else {
value = ((),propType);
}
String filedSql = (rule, (column), value,isString);
(sqlAnd+filedSql);
}
}
("query auth sql is:"+());
return ();
}
/**
* 根据权限相关配置 组装mp需要的权限
* @param queryWrapper
* @param clazz
* @return
*/
public static void installAuthMplus(MPJQueryWrapper<?> queryWrapper,Class<?> clazz) {
//权限查询
Map<String,SysPermissionDataRuleModel> ruleMap = getRuleMap();
PropertyDescriptor[] origDescriptors = (clazz);
for (String c : ()) {
if((c) && (SQL_RULES_COLUMN)){
(i ->(getSqlRuleValue((c).getRuleValue())));
}
}
String name, column;
for (int i = 0; i < ; i++) {
name = origDescriptors[i].getName();
if (judgedIsUselessField(name)) {
continue;
}
column = (clazz, name);
if(column==null){
continue;
}
if((name)) {
addRuleToQueryWrapper((name), column, origDescriptors[i].getPropertyType(), queryWrapper);
}
}
}
/**
* 转换sql中的系统变量
* @param sql
* @return
*/
public static String convertSystemVariables(String sql){
return getSqlRuleValue(sql);
}
/**
* 获取系统数据库类型
*/
private static String getDbType(){
return ();
}
/**
* mysql 模糊查询之特殊字符下划线 (_、\)
*
* @param value:
* @Return:
*/
private static String specialStrConvert(String value) {
if (DataBaseConstant.DB_TYPE_MYSQL.equals(getDbType()) || DataBaseConstant.DB_TYPE_MARIADB.equals(getDbType())) {
String[] specialStr = JoinQueryGenerator.LIKE_MYSQL_SPECIAL_STRS.split(",");
for (String str : specialStr) {
if ((str) !=-1) {
value = (str, "\\" + str);
}
}
}
return value;
}
}