国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接

這篇具有很好參考價值的文章主要介紹了Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

前言

ps:最近在參與3100保衛(wèi)戰(zhàn),戰(zhàn)況很激烈,剛剛打完仗,來更新一下之前寫了一半的博客。

該篇針對日常寫查詢的時候,那些動態(tài)條件sql 做個簡單的封裝,自動生成(拋磚引玉,搞個小玩具,不喜勿噴)。

正文

來看看我們平時寫那些查詢,基本上都要寫的一些動態(tài)sql:
?

Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接,跟我一起玩轉(zhuǎn) SpringBoot,Mybatis,spring boot,mybatis,java,自定義攔截器,動態(tài)sql

一個字段寫一個if ,有沒有人覺得煩的。

每張表的查詢,很多都有這種需求,根據(jù)什么查詢,根據(jù)什么查詢,不為空就觸發(fā)條件。

天天寫天天寫,copy 改,copy改, 有沒有人覺得煩的。


Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接,跟我一起玩轉(zhuǎn) SpringBoot,Mybatis,spring boot,mybatis,java,自定義攔截器,動態(tài)sql

可能有看官看到這就會說, 用插件自動生成就好了。
也有看官會說,用mybatis-plus就好了。

確實(shí)有道理,但是我就是想整個小玩具。你管我。

開整

本篇實(shí)現(xiàn)的封裝小玩具思路:

①制定的規(guī)則(比如標(biāo)記自定義注解 @JcSqlQuery 或是 函數(shù)命名帶上JcDynamics)。

② 觸發(fā)的查詢符合規(guī)則的, 都自動去根據(jù)傳參對象,不為空就自動組裝 sql查詢條件。

③ 利用mybatis @Select 注解,把默認(rèn)表查詢sql寫好,順便進(jìn)到自定義的mybatis攔截器里面。

④組裝完sql,就執(zhí)行,完事。

先寫mapper函數(shù) :
?

/**
 * @Author JCccc
 * @Description
 * @Date 2023/12/14 16:56
 */
@Mapper
public interface DistrictMapper {

    @Select("select code,name,parent_code,full_name  FROM s_district_info")
    List<District> queryListJcDynamics(District district);

    @Select("select code,name,parent_code,full_name  FROM s_district_info")
    District queryOneJcDynamics(District district);

}

Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接,跟我一起玩轉(zhuǎn) SpringBoot,Mybatis,spring boot,mybatis,java,自定義攔截器,動態(tài)sql

然后是ParamClassInfo.java 這個用于收集需要參與動態(tài)sql組裝的類:

?

import lombok.Data;

/**
 * @Author JCccc
 * @Description
 * @Date 2021/12/14 16:56
 */
@Data
public class ParamClassInfo {

    private  String classType;
    private  Object keyValue;
    private  String  keyName;

}

然后是一個自定義的mybatis攔截器(這里面寫了一些小函數(shù)實(shí)現(xiàn)自主組裝,下面有圖解) :


MybatisInterceptor.java

import com.example.dotest.entity.ParamClassInfo;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.*;


/**
 * @Author JCccc
 * @Description
 * @Date 2021/12/14 16:56
 */
@Component
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class MybatisInterceptor implements Interceptor {


    private final static String JC_DYNAMICS = "JcDynamics";

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //獲取執(zhí)行參數(shù)
        Object[] objects = invocation.getArgs();
        MappedStatement ms = (MappedStatement) objects[0];
        Object objectParam = objects[1];
        List<ParamClassInfo> paramClassInfos = convertParamList(objectParam);
        String queryConditionSqlScene = getQueryConditionSqlScene(paramClassInfos);
        //解析執(zhí)行sql的map方法,開始自定義規(guī)則匹配邏輯
        String mapperMethodAllName = ms.getId();
        int lastIndex = mapperMethodAllName.lastIndexOf(".");
        String mapperClassStr = mapperMethodAllName.substring(0, lastIndex);
        String mapperClassMethodStr = mapperMethodAllName.substring((lastIndex + 1));
        Class<?> mapperClass = Class.forName(mapperClassStr);
        Method[] methods = mapperClass.getMethods();
        for (Method method : methods) {
            if (method.getName().equals(mapperClassMethodStr) && mapperClassMethodStr.contains(JC_DYNAMICS)) {
                BoundSql boundSql = ms.getSqlSource().getBoundSql(objects[1]);
                String originalSql = boundSql.getSql().toLowerCase(Locale.CHINA).replace("[\\t\\n\\r]", " ");
                //進(jìn)行自動的 條件拼接
                String newSql = originalSql + queryConditionSqlScene;
                BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), newSql,
                        boundSql.getParameterMappings(), boundSql.getParameterObject());
                MappedStatement newMs = newMappedStatement(ms, new MyBoundSqlSqlSource(newBoundSql));
                for (ParameterMapping mapping : boundSql.getParameterMappings()) {
                    String prop = mapping.getProperty();
                    if (boundSql.hasAdditionalParameter(prop)) {
                        newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
                    }
                }
                Object[] queryArgs = invocation.getArgs();
                queryArgs[0] = newMs;
                System.out.println("打印新SQL語句" + newSql);
            }
        }
        //繼續(xù)執(zhí)行邏輯
        return invocation.proceed();
    }

    private String getQueryConditionSqlScene(List<ParamClassInfo> paramClassInfos) {
        StringBuilder conditionParamBuilder = new StringBuilder();
        if (CollectionUtils.isEmpty(paramClassInfos)) {
            return "";
        }
        conditionParamBuilder.append("  WHERE ");
        int size = paramClassInfos.size();
        for (int index = 0; index < size; index++) {
            ParamClassInfo paramClassInfo = paramClassInfos.get(index);
            String keyName = paramClassInfo.getKeyName();
            //默認(rèn)駝峰拆成下劃線 ,比如 userName -》 user_name ,   name -> name
            //如果是需要取別名,其實(shí)可以加上自定義注解這些,但是本篇例子是輕封裝,思路給到,你們i自己玩
            String underlineKeyName = camelToUnderline(keyName);
            conditionParamBuilder.append(underlineKeyName);
            Object keyValue = paramClassInfo.getKeyValue();
            String classType = paramClassInfo.getClassType();
            //其他類型怎么處理 ,可以按照類型區(qū)分 ,比如檢測到一組開始時間,Date 拼接 between and等
//            if (classType.equals("String")){
//                conditionParamBuilder .append("=").append("\'").append(keyValue).append("\'");
//            }

            conditionParamBuilder.append("=").append("\'").append(keyValue).append("\'");
            if (index != size - 1) {
                conditionParamBuilder.append(" AND ");
            }
        }
        return conditionParamBuilder.toString();
    }

    private static List<ParamClassInfo> convertParamList(Object obj) {
        List<ParamClassInfo> paramClassList = new ArrayList<>();
        for (PropertyDescriptor pd : BeanUtils.getPropertyDescriptors(obj.getClass())) {
            if (!"class".equals(pd.getName())) {
                if (ReflectionUtils.invokeMethod(pd.getReadMethod(), obj) != null) {
                    ParamClassInfo paramClassInfo = new ParamClassInfo();
                    paramClassInfo.setKeyName(pd.getName());
                    paramClassInfo.setKeyValue(ReflectionUtils.invokeMethod(pd.getReadMethod(), obj));
                    paramClassInfo.setClassType(pd.getPropertyType().getSimpleName());
                    paramClassList.add(paramClassInfo);
                }
            }
        }
        return paramClassList;
    }


    public static String camelToUnderline(String line){
        if(line==null||"".equals(line)){
            return "";
        }
        line=String.valueOf(line.charAt(0)).toUpperCase().concat(line.substring(1));
        StringBuffer sb=new StringBuffer();
        Pattern pattern= compile("[A-Z]([a-z\\d]+)?");
        Matcher matcher=pattern.matcher(line);
        while(matcher.find()){
            String word=matcher.group();
            sb.append(word.toUpperCase());
            sb.append(matcher.end()==line.length()?"":"_");
        }
        return sb.toString();
    }


    @Override
    public Object plugin(Object o) {
        //獲取代理權(quán)
        if (o instanceof Executor) {
            //如果是Executor(執(zhí)行增刪改查操作),則攔截下來
            return Plugin.wrap(o, this);
        } else {
            return o;
        }
    }

    /**
     * 定義一個內(nèi)部輔助類,作用是包裝 SQL
     */
    class MyBoundSqlSqlSource implements SqlSource {
        private BoundSql boundSql;

        public MyBoundSqlSqlSource(BoundSql boundSql) {
            this.boundSql = boundSql;
        }

        @Override
        public BoundSql getBoundSql(Object parameterObject) {
            return boundSql;
        }

    }

    private MappedStatement newMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
        MappedStatement.Builder builder = new
                MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());
        if (ms.getKeyProperties() != null && ms.getKeyProperties().length > 0) {
            builder.keyProperty(ms.getKeyProperties()[0]);
        }
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());
        builder.resultMaps(ms.getResultMaps());
        builder.resultSetType(ms.getResultSetType());
        builder.cache(ms.getCache());
        builder.flushCacheRequired(ms.isFlushCacheRequired());
        builder.useCache(ms.isUseCache());
        return builder.build();
    }


    @Override
    public void setProperties(Properties properties) {
        //讀取mybatis配置文件中屬性
    }


代碼簡析:

駝峰轉(zhuǎn)換下劃線,用于轉(zhuǎn)出數(shù)據(jù)庫表的字段 :

Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接,跟我一起玩轉(zhuǎn) SpringBoot,Mybatis,spring boot,mybatis,java,自定義攔截器,動態(tài)sql

通過反射把 sql入?yún)⒌膶ο?不為空的屬性名和對應(yīng)的值,拿出來:

Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接,跟我一起玩轉(zhuǎn) SpringBoot,Mybatis,spring boot,mybatis,java,自定義攔截器,動態(tài)sql

組件動態(tài)查詢的sql 語句 :

Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接,跟我一起玩轉(zhuǎn) SpringBoot,Mybatis,spring boot,mybatis,java,自定義攔截器,動態(tài)sql

寫個簡單測試用例:

    @Autowired
    DistrictMapper districtMapper;

    @Test
    public void test() {
        District query = new District();
        query.setCode("110000");
        query.setName("北京市");
        District district = districtMapper.queryOneJcDynamics(query);
        System.out.println(district.toString());

        District listQuery = new District();
        listQuery.setParentCode("110100");
        List<District> districts = districtMapper.queryListJcDynamics(listQuery);
        System.out.println(districts.toString());
    }

?看下效果,可以看到都自動識別把不為空的字段屬性和值拼接成查詢條件了:

Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接,跟我一起玩轉(zhuǎn) SpringBoot,Mybatis,spring boot,mybatis,java,自定義攔截器,動態(tài)sql

?Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接,跟我一起玩轉(zhuǎn) SpringBoot,Mybatis,spring boot,mybatis,java,自定義攔截器,動態(tài)sql

好了,該篇就到這。 拋磚引玉,領(lǐng)悟分步封裝思路最重要,都去搞些小玩具娛樂娛樂吧。文章來源地址http://www.zghlxwxcb.cn/news/detail-655806.html

到了這里,關(guān)于Springboot 封裝整活 Mybatis 動態(tài)查詢條件SQL自動組裝拼接的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • java springboot整合MyBatis實(shí)現(xiàn)分頁查詢以及帶條件的分頁查詢

    java springboot整合MyBatis實(shí)現(xiàn)分頁查詢以及帶條件的分頁查詢

    之前的文章 java springboot整合MyBatis做數(shù)據(jù)庫查詢操作操作了springboot整合MyBatis,然后簡單做了個按id查詢的操作 那么 我們按上文搭建起的環(huán)境繼續(xù) 我們直接在staffDao接口中聲明一個分頁函數(shù) 這里 我們直接在 sql語句中寫limit 分頁邏輯 參數(shù)是方法接收的 這個函數(shù)接收兩個參數(shù)

    2024年02月10日
    瀏覽(22)
  • MyBatis多表查詢+動態(tài)sql

    MyBatis多表查詢+動態(tài)sql

    在全局配置文件中中設(shè)置MyBatis執(zhí)行日志 假設(shè)有一個用戶表和文章表,實(shí)體類中一個關(guān)聯(lián)關(guān)系。 用戶實(shí)體類 文章實(shí)體類 如果想查詢的結(jié)果包含UserInfo的信息就需要使用,?對?映射要使? association 標(biāo)簽,因?yàn)橐黄恼轮荒軐?yīng)一個作者。 Controller控制器代碼 Service服務(wù)層代碼

    2023年04月19日
    瀏覽(27)
  • mybatis xml多表查詢,子查詢,連接查詢,動態(tài)sql

    mybatis xml多表查詢,子查詢,連接查詢,動態(tài)sql

    student_type 表 student 表 Student 類 一個學(xué)生只有一個年級 Type 類 一個年級有多個學(xué)生,所以用 list 下列代碼中: 1 resultMap 里面property對應(yīng)實(shí)體類屬性,column對應(yīng)數(shù)據(jù)庫字段名 2 主鍵用 id 標(biāo)簽 其他用result 3 關(guān)聯(lián)查詢(子查詢和連接查詢) 連接查詢查一次 4 一個年級多個學(xué)生,所以

    2024年01月21日
    瀏覽(18)
  • MyBatis動態(tài)SQL、模糊查詢與結(jié)果映射

    MyBatis動態(tài)SQL、模糊查詢與結(jié)果映射

    目錄 前言 一、MyBatis動態(tài)SQL 1.動態(tài)SQL是什么 2.動態(tài)SQL的作用 3.常用動態(tài)SQL元素 1. where + if 元素 2. set + if 元素 3. choose + when + otherwise 元素 4. 自定義 trim 元素 ?1. 自定義 trim 元素改寫上面的 where + if 語句 2. 自定義 trim 元素改寫上面的 set + if 語句 5. foreach 元素 6.SQL片段重用 二、

    2024年02月11日
    瀏覽(45)
  • MyBatis(多表查詢,動態(tài)SQL的使用)

    MyBatis(多表查詢,動態(tài)SQL的使用)

    目錄 多表查詢 ?查詢文章詳情 查詢一個用戶底下的所有文章 動態(tài)SQL的使用 if 標(biāo)簽 trim 標(biāo)簽 ?where 標(biāo)簽 set 標(biāo)簽 foreach 標(biāo)簽 現(xiàn)在有倆張表,一張是 文章表 ,一張是 用戶表 .如下: 我們現(xiàn)在想查詢得到一張表,表里面的內(nèi)容和文章表大多一致,只是要 在文章表的基礎(chǔ)上添加用戶表中

    2024年02月10日
    瀏覽(23)
  • 【MyBatis 學(xué)習(xí)三】子段不一致問題 && 多表查詢 && 動態(tài)SQL

    【MyBatis 學(xué)習(xí)三】子段不一致問題 && 多表查詢 && 動態(tài)SQL

    目錄 一、解決Java實(shí)體類屬性與數(shù)據(jù)庫表字段不一致問題 ??現(xiàn)象1:顯示字段不對應(yīng):使用ResultType查詢結(jié)果為null; ??解決辦法:字段不對應(yīng):使用ResultMap解決。 二、數(shù)據(jù)庫的多表查詢 ??方式1:使用對象user? ??方式2:直接寫具體的屬性 三、動態(tài)SQL的使用 ??1、if標(biāo)簽:單

    2024年02月15日
    瀏覽(21)
  • Mybatis-Plus詳解(新建maven項(xiàng)目、查詢所有信息、打印SQL日志、實(shí)現(xiàn)CRUD(增刪改查)、分頁、條件查詢且分頁,前后端分離式開發(fā))

    Mybatis-Plus詳解(新建maven項(xiàng)目、查詢所有信息、打印SQL日志、實(shí)現(xiàn)CRUD(增刪改查)、分頁、條件查詢且分頁,前后端分離式開發(fā))

    MyBatis-Plus(opens new window) (簡稱MP) 是一個MyBatis(opens new window)的增強(qiáng)工具,在MyBatis的基礎(chǔ)上只做增強(qiáng)不做改變,為簡化開發(fā)、提高效率而生。想查看官網(wǎng)相關(guān)內(nèi)容的化我這里提供了官網(wǎng)地址:https://baomidou.com/ 無侵入:只做增強(qiáng)不做改變,引入它不會對現(xiàn)有工程產(chǎn)生影響,如絲般

    2024年02月04日
    瀏覽(22)
  • MyBatis進(jìn)階:掌握MyBatis動態(tài)SQL與模糊查詢、結(jié)果映射,讓你在面試中脫穎而出!!

    MyBatis進(jìn)階:掌握MyBatis動態(tài)SQL與模糊查詢、結(jié)果映射,讓你在面試中脫穎而出!!

    目錄 一、引言 二、MyBatis動態(tài)SQL 2.1.if元素使用 2.2.foreach元素使用 三、MyBatis模糊查詢 ①使用#{字段名} ②使用${字段名} ③使用concat{\\\'%\\\',#{字段名},\\\'%\\\'} 總結(jié) 四、MyBatis結(jié)果映射 4.1.案例演示 4.1.1.resultType進(jìn)行結(jié)果映射 4.1.2.resultMap進(jìn)行結(jié)果映射 在當(dāng)今的軟件開發(fā)環(huán)境中,數(shù)據(jù)庫的使

    2024年02月11日
    瀏覽(21)
  • mybatis-plus技巧--動態(tài)表名-多語句-拼接sql--關(guān)于mybatis的mysql分頁查詢總數(shù)的優(yōu)化思考

    mybatis-plus技巧--動態(tài)表名-多語句-拼接sql--關(guān)于mybatis的mysql分頁查詢總數(shù)的優(yōu)化思考

    傳入tableName參數(shù)就可以了,不過只能用$不能用# 因?yàn)?會發(fā)生預(yù)編譯,然后會在表名上加引號’\\\'。 新建一個表名攔截類實(shí)現(xiàn)TableNameHandler mybatisPlus添加插件 實(shí)例: 每天按統(tǒng)計 如果表名為count則加上今天的時間 每次設(shè)置 直接設(shè)置名字,然后就會改變的。 需要在配置文件中的

    2024年01月16日
    瀏覽(23)
  • Mybatis-puls——條件查詢的三種格式+條件查詢null判定+查詢投影

    Mybatis-puls——條件查詢的三種格式+條件查詢null判定+查詢投影

    在mybatis_plus的封裝中的WrapperT接口參數(shù)就是用于封裝查詢條件? ?在測試類中啟動如上一個簡單的查詢,然后控制臺運(yùn)行會輸出一大堆無關(guān)日志,這里先把這些日志關(guān)閉 先新建一個XML配置文件? ?然后變成如下,這里configuration標(biāo)簽里面什么都沒有配置就是取消所有日志文件了

    2024年01月18日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包