美文网首页
数据库,“你”的空格,我来处理!

数据库,“你”的空格,我来处理!

作者: 极简博客 | 来源:发表于2021-05-25 15:40 被阅读0次

Mybatis在做数据库查询更新操作时,是否有遇到过字段前后出现空格的的情况;如果有,你是怎么处理的?是一个个trim()还是如何处理,接下来我将谈谈我的做法:使用拦截器注解@Intercepts告别字符串前后空格。

Exceutor

Excutor是Mybatis的最核心的接口之一。其中,SqlSession接口中的功能就是基于Excutor来完成的。我们所需要的拦截的,也是这个接口所定义的CRUD操作方法:query

package org.apache.ibatis.executor;

import java.sql.SQLException;
import java.util.List;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.transaction.Transaction;

/**
 * Mybatis执行器
 *
 * @author Clinton Begin
 */
public interface Executor {
    /**
     * 默认的结果处理器,默认为空,主要是在查询的时候用于处理查询结果
     */
    ResultHandler NO_RESULT_HANDLER = null;

    /**
     * 实现对数据表的insert/update/delete操作
     * @param ms
     * @param parameter
     * @return
     * @throws SQLException
     */
    int update(MappedStatement ms, Object parameter) throws SQLException;

    /**
     * 查询,回调处理查询结果,带分页
     * @param ms
     * @param parameter
     * @param rowBounds
     * @param resultHandler
     * @param cacheKey
     * @param boundSql
     * @param <E>
     * @return
     * @throws SQLException
     */
    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;

    /**
     * 查询,回调处理查询结果
     * @param ms
     * @param parameter
     * @param rowBounds
     * @param resultHandler
     * @param <E>
     * @return
     * @throws SQLException
     */
    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;

    /**
     * 查询,返回游标类型
     * @param ms
     * @param parameter
     * @param rowBounds
     * @param <E>
     * @return
     * @throws SQLException
     */
    <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;

    /**
     * 批量处理sql语句
     * @return
     * @throws SQLException
     */
    List<BatchResult> flushStatements() throws SQLException;

    /**
     * 提交事务
     * @param required
     * @throws SQLException
     */
    void commit(boolean required) throws SQLException;

    /**
     * 回滚事务
     * @param required
     * @throws SQLException
     */
    void rollback(boolean required) throws SQLException;

    /**
     * 创建缓存中使用的CacheKey,即缓存中使用的key
     * @param ms
     * @param parameterObject
     * @param rowBounds
     * @param boundSql
     * @return
     */
    CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);

    /**
     * 根据对应的key,查找是否存在缓存
     * @param ms
     * @param key
     * @return
     */
    boolean isCached(MappedStatement ms, CacheKey key);

    /**
     * 清理一级缓存
     */
    void clearLocalCache();

    /**
     * 延迟加载一级缓存中的数据
     * @param ms
     * @param resultObject
     * @param property
     * @param key
     * @param targetType
     */
    void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);

    /**
     * 获取事务对象
     * @return
     */
    Transaction getTransaction();

    /**
     * 关闭Executor对象
     * @param forceRollback
     */
    void close(boolean forceRollback);

    /**
     * 检查Exceutor对象是否关闭
     * @return
     */
    boolean isClosed();

    /**
     * 设置包装类
     * @param executor
     */
    void setExecutorWrapper(Executor executor);

}

拦截器

@Intercepts用于表明当前的对象是一个Interceptor

@Signature则表明要拦截的接口、方法以及对应的参数类型

package com.bly.crm.server.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bly.crm.generic.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @Author: Cpz
 * @Description: 去除数据库查询返回结果集中字符串出现前后空格的情况
 * eg: (1) " 文艺 " => " 文艺 ".trim() => "文艺"
 *     (2) "     " => "      ".trim() => null
 * @Date: 2021/5/24 10:36
 * @Version: 1.0
 */
@Slf4j
@Component
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})
})
public class MybatisInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        // 获取查询返回类型
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        List<ResultMap> resultMaps = mappedStatement.getResultMaps();
        Class<?> resultType = resultMaps.get(0).getType();

        // 获取查询结果并做空判断
        Object proceed = invocation.proceed();
        JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(proceed));
        if (jsonArray.isEmpty()) {
            return proceed;
        }

        // 返回结果不为空则开始去除字符串前后空格
        for (int i = 0, l = jsonArray.size(); i < l; i++) {
            Object o = jsonArray.get(i);
            if (o instanceof JSONObject) {
                JSONObject jsonObject = (JSONObject) o;
                for (String key : jsonObject.keySet()) {
                    Object value = jsonObject.get(key);
                    if (value instanceof String) {
                        jsonObject.put(key, StringUtils.trim2null(String.valueOf(value)));
                    }
                }
                o = jsonObject;
            }else if (o instanceof String){
                o = StringUtils.trim2null(String.valueOf(o));
            }
            jsonArray.set(i, o);
        }

        // 还原本来对象并返回
        return JSON.parseArray(jsonArray.toJSONString(), resultType);
    }
}

配置拦截器插件

private final MybatisInterceptor mybatisInterceptor;

/**
 * 配置mybatis分页插件和自定义拦截器
 * @param bean
 */
private void setSqlSessionFactoryPlugins(MybatisSqlSessionFactoryBean bean) {
    MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
    PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor();
    mybatisPlusInterceptor.addInnerInterceptor(paginationInterceptor);
    bean.setPlugins(mybatisPlusInterceptor, mybatisInterceptor);
}

拓展

在接口传参的时候,也可能出现类似的情况,可以通过拦截mybatis的update方法实现空格去除,这里就不过多赘述。

@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})

相关文章

  • 数据库,“你”的空格,我来处理!

    Mybatis在做数据库查询更新操作时,是否有遇到过字段前后出现空格的的情况;如果有,你是怎么处理的?是一个个tr...

  • CSS 的空格处理

    文章转自 阮一峰博客:http://www.ruanyifeng.com/blog/2018/07/white-s...

  • 异常空格处理

    有一次处理数据时,需要去掉数据中的空数据,即下图: 使用去空格的方法:trim()函数、正则表达式匹配: 但是都不...

  • 练习0.0.0

    -题目不难做,问题是如何处理姓名中间的空格,如果不用到getline函数,你就要写上一大段代码去处理空格,(QAQ...

  • EXCEL学习笔记

    excel函数学习 前期处理类 trim 去除空格,很多数据里面有空格,不方便处理 具体操作 选择处理后的数据存放...

  • 处理字符串首尾空格

    处理字符串首尾空格

  • 对前程无忧的初步爬取

    爬取的网页 里面有空格要处理下 网页处理

  • 2018-05-24Ubuntu 18.04桌面版下使用Dbea

    Ubuntu下Dbeaver community 连接mysql8 标签(空格分隔): mysql 数据库 数据库...

  • SQLite数据库基础(完结)

    标签(空格分隔): iOS数据库 数据库总结 SQLite数据库 ios中的数据存储方式及其特点 Preferen...

  • iOS SQLite数据库基础

    标签(空格分隔): iOS数据库 数据库总结 SQLite数据库 ios中的数据存储方式及其特点 Preferen...

网友评论

      本文标题:数据库,“你”的空格,我来处理!

      本文链接:https://www.haomeiwen.com/subject/fmqcsltx.html