springboot通用查询方法,一个方法解决所有领域资源的条件查询操作

        基本大多数的项目,条件查询模块都是每个领域对象都有一个条件查询的controller,多个界面中甚至有很多重复的条件,例如编号、名称等属性。那么我们能不能只写一个通用查询接口,来适用与大多数的条件查询呢?在service层中的逻辑处理,我们封装为一个方法返回sql语句,这样即便有特殊情况使我们的通用查询不能处理时,也能及时的更改sql语句。

        sql语句大家都很熟悉,例如

select userNo, name from tbUser where id = '3d96926a-0124-4c1f-ae62-704ad3ae5df3
'

        显而易见,我们要解决的是如何获取sql中需要的信息,例如表名、where后面的条件。

        首先,表名肯定是不能由前端来传递过来,这样并不符合我们的代码规范,那我们该怎么拿到我们的表名呢?我们可以将我们的请求url中添加领域对象的名称,例如下图controller

         通用查询只能适用于后端,对前端来讲还是每个对象多要调用一次后台。前台将{entity}中填入想要查询对象的名称。

        后端获取前端所传的领域对象名,根据代码规范,我们的领域对象都应在同一包下,加上所在包路径,通过反射来获取领域对象类的信息。

        接下来我们要通过领域对象类来获取对应数据库的表名。

        首先我们要自定义一个注解,功能很简单,根据实体类来获取对应的数据库表名。自定义注解代码如下

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface TableName {

    public String name();

}

        该注解的使用如下

我们首先通过前端所传的领域对象名称获取到该类,,然后根据我们的自定义注解获取表名

 这个接受参数是我自己封装的一个类,很简单

public class SearchParam {

    /**
     * 字段名称
     */
    private String fieldName;
    /**
     * 操作符 默认为 =
     */
    private String op;
    /**
     * 字段值
     */
    private String fieldValue;
}

现在表名有了,查询条件有了,我们可以开始拼装sql语句了

StringBuilder sb = new StringBuilder();
if (searchParams.size() > 0) {
    sb.append(" where ");
    for (SearchParam searchParam : searchParams) {
        if (searchParam.getFieldName().contains(".")) {
            sb.append(searchParam.getFieldName());
        } else {
            sb.append(alias).append(".").append(searchParam.getFieldName());
        }
        if (StringUtils.isBlank(searchParam.getOp())) {
            sb.append(" = ");
        } else {
            sb.append(" ").append(searchParam.getOp()).append(" ");
        }
        try {
            Class classzz = Class.forName(className);
            Field field = classzz.getDeclaredField(searchParam.getFieldName());
            String simpleName = field.getType().getSimpleName();
            if ("String".equals(simpleName)) {
                if ("like".equals(searchParam.getOp())) {
                    sb.append("'%").append(filter(searchParam.getFieldValue())).append("%'");
                } else {
                    sb.append("'").append(filter(searchParam.getFieldValue())).append("'");
                }
            } else if ("Integer".equals(simpleName) || "BigDecimal".equals(simpleName) || "LocalDateTime".equals(simpleName)) {
                sb.append(filter(searchParam.getFieldValue()));
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        sb.append(" and ");
    }
    sb.delete(sb.length() - 4, sb.length());
}
return String.format("select * from %s %s %s", tableName, alias, ObjectUtils.isEmpty(sb) ? "" : sb);

         这个方法直接返回拼装好的sql语句,这样我们就只能使用mybatis的$符了,但是$无法防sql注入,所以我们要在程序中防止sql注入,具体代码如下

/**
 * 防止sql注入
 *
 * @param param 过滤前字符串
 * @return 过滤后字符串
 */
public static String filter(String param) {
    String regex = "'|%|--|and|or|not|use|insert|delete|update|select|count|group|union|" +
            "|create|drop|truncate|alter|grant|execute|xp_cmdshell|call|declare|source|sql";
    if (param == null) {
        return param;
    }
    return param.replaceAll("(?i)" + regex, "");
}

        方法返回sql语句,可有特殊需求可根据实际情况进行更改。

        仅提供思路供借鉴,以上代码为娱乐时所写,可运行及正常使用,但不建议。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

差点资深程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值