SQL或者JPQL语句拼装工具

博主探讨了在使用JPA时,面对多表关联和动态条件查询的挑战,认为直接使用MyBatis可能更为方便。然而,为了解决JPA中动态SQL拼装的问题,博主分享了自己花费三天时间开发的一个工具类,用于生成类似MyBatis SQL.java的动态查询语句,以减少代码耦合和提高灵活性。虽然已有解决方案并不完善,博主希望通过社区的力量优化这个工具类,并给出了具体的使用示例。
摘要由CSDN通过智能技术生成

第一次发博客,不知道该怎么写,算了直接提出问题吧先:

现在持久层框架用的最多的应该是hibernate、mybatis或者包含现在的jpa吧,也是前两天接触jpa,我也不晓得为什么这玩意能火起来而且尤其是国外用的比mybatis多的多的多,我擦,百思不得其解。想了半天也只有在不使用多表或者动态多条件的情况下这东西能用用,可是哪个应用会出现全部功能都是单表操作呢,我估计很少吧。所以与其代码中写一大推原生sql,拼接各种条件,然后返回自定义对象可能还不是那么完美的情况下,直接使用mybatis它不香么…

okok,跑偏了,说说今天的主题:假如你用了jpa并且有多表关联很可能还有很多动态条件(可以传值可以为空,传值时动态拼接查询语句),那么代码中耦合sql语句并且各种 if 判空,这显得非常不优雅而且在业务变动的情况下很麻烦,所以想到了有没有类似mybatis中的动态语句生成工具 SQL.java这个类,原本是想着直接拿过来用,结果遗憾的是mybatis中的这个工具并不能达到我的需求,不是那么健全。基于这个情况在网上也没有找到合适的工具类(不重复造轮子我们只是轮子的搬运工),因此花了三天死掉了好多脑细胞的情况下自己搞了一个工具类(主要废弃了好几种方案最终采用了目前的这个),代码不多也很简单,就是装的不够优雅所以发出来让大家帮忙优化优化。

举个例子:假如我们有以下这么一个jpa查询,并且班级、性别和年龄条件都是动态的,这个业务含义应该不用解释很简单,

select s from Student s where class='class2' and ((age>=20 and sex='男') or (age <=16 and sex = '女'))

那么可以按照如下写法:

Cnd.select("select s from Student s")
.andExp("name","like","%张三%")
.andExp("class","=","class2")
.andExps(Cnd.exps(Cnd.exp("age",">=","20").andExp("sex","=","男")).orExps(Cnd.exp("age","<=","16").andExp("sex","=","女")));

执行后生成的SQL语句长这样:

select s from Student s where name like :name_0 and class = :class_0 and ((age >= :age_0 and sex = :sex_0) or (age <= :age_1 and sex = :sex_1))

然后Cnd中会封装查询参数,可以用在后边查询流程:
在这里插入图片描述

一般业务不会太复杂,但是条件可以是动态的,上边写法当名称或者年龄为空时生成的查询语句不会包含这个条件

so还是挺简单,直接上代码,

public class Cnd {
   
    private String select = "";
    private StringBuilder cndStr = new StringBuilder();
    private Map<String, Object> conditions = new HashMap<String, Object>();

    private Cnd() {
   
    }

    /**
     * 获取条件表达式
     * @param ql 查询语句
     */
    public static Cnd select(String ql) {
   
        Cnd cnd = new Cnd();
        cnd.select = ql;
        return cnd;
    }

    /**
     * 获取条件表达式
     *
     * @param name
     * @param operator
     * @param value
     * @return
     */
    public static Cnd exp(String name, String operator, Object value) {
   
        Cnd cnd = new Cnd();
        if(!cnd.validate(value)) {
   
            return cnd;
        }
        String alias = cnd.setAlias(name,value);
        cnd.cndStr.append(" where ").append(name).append(" ").append(operator).append(" ").append(":").append(alias);
        return cnd;
    }

    /**
     * 获取条件表达式组
     *
     * @param cnd
     * @return
     */
    public static Cnd exps(Cnd cnd) {
   
        Cnd cnd1 = new Cnd();
        cnd1.andExps(cnd);
        return cnd1;
    }

    /**
     * 增加 and条件表达式
     *
     * @param name
     * @param operator
     * @param value
     * @return
     */
    public Cnd andExp(String name, String operator, Object value) {
   
        if(!validate(value)) {
   
            return this;
        }
        if(value instanceof Cnd) {
   
            Cnd cnd = (Cnd)value;
            Iterator<Map.Entry<String, Object>> entries = cnd.conditions.entrySet().iterator();
            while (entries.hasNext()) {
   
                Map.Entry<String, Object> entry = entries.next();
                String k = entry.getKey();
                Object v = entry.getValue();
                String alias = setAlias(k,v);
                cnd.cndStr.replace(cnd.cndStr.indexOf(k),cnd.cndStr.indexOf(k)+k.length(),alias);
                conditions.put(alias,v);
            }
            if(cnd.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值