首页 > 其他分享 >Mybatis-Plus取消自动转驼峰拦截器

Mybatis-Plus取消自动转驼峰拦截器

时间:2023-02-22 19:56:07浏览次数:47  
标签:拦截器 java target ibatis apache Plus org Mybatis import

背景

  • 项目使用Mybatis-Plus,开启了全局结果集字段转驼峰map-underscore-to-camel-case: true。开启之后如果需要返回下划线需要自定义resultMap
  • 现需要返回List<Map>,且返回的字段是动态变化,需要返回原Sql中的AS后的字段

版本

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>2.5.3</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.18</version>
</dependency>

解决

  • 由于开启了map-underscore-to-camel-case: true全局驼峰,在org.apache.ibatis.executor.resultset.DefaultResultSetHandler#createAutomaticMappings方法中使用,且在com.baomidou.mybatisplus.extension.handlers.MybatisMapWrapper#findProperty方法中进行了转换。暂时没有找到其他的扩展点,故只能通过拦截器在结果集中处理
  • 通过在拦截器中识别方法的注解,对结果进行拦截

@CancelCamelCase

import java.lang.annotation.*;

/**
 * @author wf
 * @date 2022年08月10日 11:14
 * @description SQL获取
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CancelCamelCase {
}

CancelCamelCaseInterceptor

  • 执行SQL之前先保存本身的下划线字段到一个map,然后等执行完SQL之后再还原回来
import com.alibaba.druid.pool.DruidPooledPreparedStatement;
import com.google.common.collect.Maps;
import com.wf.dev.common.annotaions.CancelCamelCase;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.assertj.core.util.Lists;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author wf
 * @date 2023年01月10日 10:40
 * @description 对mybatis查询单独取消map-underscore-to-camel-case为true
 */
@Component
@Intercepts(@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}))
public class CancelCamelCaseInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        DefaultResultSetHandler resultSetHandler = (DefaultResultSetHandler) invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(resultSetHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("mappedStatement");
        String namespace = mappedStatement.getId();
        String className = StringUtils.substringBeforeLast(namespace, ".");
        Class<?> clazz = Class.forName(className);
        if (!clazz.isAnnotationPresent(CancelCamelCase.class)) {
            return invocation.proceed();
        }
        String methodName = StringUtils.substringAfterLast(namespace, ".");
        Method[] methods = clazz.getMethods();
        Method target = null;
        for (Method method : methods) {
            if (!method.getName().equals(methodName)) {
                continue;
            }
            target = method;
            break;
        }
        if (target == null || !target.isAnnotationPresent(CancelCamelCase.class)) {
            return invocation.proceed();
        }
        DruidPooledPreparedStatement ms = (DruidPooledPreparedStatement) invocation.getArgs()[0];
        ResultSet resultSet = ms.getResultSet();
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        Map<String, String> propertyColumnNameMap = Maps.newHashMap();
        for (int i = 1; i <= columnCount; i++) {
            // 这里必须要用getColumnLabel,不能用getColumnName
            String columnName = metaData.getColumnLabel(i);
            propertyColumnNameMap.put(com.baomidou.mybatisplus.core.toolkit.StringUtils.underlineToCamel(columnName), columnName);
        }
        Object proceed = invocation.proceed();
        if (!(proceed instanceof List)) {
            return proceed;
        }
        List list = (List) proceed;
        List<Map<String, Object>> result = Lists.newArrayList();
        for (Object row : list) {
            MetaObject metaObjectRow = MetaObject.forObject(row, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
            Map<String, Object> newRow = Maps.newHashMap();
            for (String property : propertyColumnNameMap.keySet()) {
                newRow.put(propertyColumnNameMap.get(property), metaObjectRow.getValue(property));
            }
            result.add(newRow);
        }
        return result;
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof ResultSetHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

Mapper

import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**
 * @author wf
 * @date 2023年01月10日 15:07
 * @description
 */
@CancelCamelCase
public interface Mapper {

    /**
     * 从sql查询
     *
     * @param param
     * @return
     */
    @CancelCamelCase
    List<Map<String, Object>> sqlQuery(QueryParam param);
}

小结

  • 此方法还是比较死板,增加了for循环,等于效率降低了。需要寻求更多的扩展

参考

标签:拦截器,java,target,ibatis,apache,Plus,org,Mybatis,import
From: https://www.cnblogs.com/wftop1/p/17145655.html

相关文章

  • day01-Mybatis介绍与入门
    Mybatis介绍与入门1.官方文档Mybatis中文手册:mybatis–MyBatis3或者MyBatis中文网Maven仓库:MavenRepository:org.mybatis»mybatis»3.5.7(mvnrepository.c......
  • 使用Jmockit 测试 spring + mybatis plus 项目 - CRUD Mapper 查询样例
    Jmockit1.46+junit4packagexxx;XXXProgressimportxxx;importcom.baomidou.mybatisplus.core.conditions.Wrapper;importcom.google.common.collect.Lists;impo......
  • 【MyBatis整合Spring开发+MyBatis多对多关联查询】
    MyBatis整合Spring开发本文关键词SqlSessionFactoryBeanMapperScannerConfigurer一、引言JDBC规范了Java编程如何去操作数据库,MyBatis框架让程序开发更集中于关键的sql编写......
  • WorkPlus“Meet”,让企业高效协作的视频会议系统
    随着办公方式的多元化,数智化办公正在逐渐进入企事业单位。保持员工移动和远程高效工作的关键是为他们提供正确的协作工具以及最佳的连接性。高效的音视频会议系统成为办公......
  • Mybatis - 在idea中错误:Invalid bound statement (not found)
    学习mybatis的过程中,测试mapper自动代理的时候一直出错,在eclipse中可以正常运行,而同样的代码在idea中却无法成功。虽然可以继续调试,但心里总是纠结原因。百度了好久,终于找到......
  • mybatis - 连接mysql数据库插入中文乱码
    对于mysql数据库的乱码问题,有两中情况:1.mysql数据库编码问题(建库时设定)。2.连接mysql数据库的url编码设置问题。对于第一个问题:目前个人发现只能通过重新建库解决,建库......
  • Spring MVC - 拦截器实现 和 用户登陆例子
    1.拦截器 SpringMvc中的拦截器实现了HandlerInterceptor接口,通常使用与身份认证,授权和校验,模板视图,统一处理等;  publicclassHanderInterceptor1implementsHandlerI......
  • 你什么档次?敢和我用一样的即时通讯平台WorkPlus?
    现今,很多企业越来越青睐私有化部署,尤其是在选择组织内部即时通讯平台的时候,更是会提出私有化部署的需求。究其原因,企业选择私有化部署即时通讯软件完全是出于安全方面考虑。......
  • WorkPlus“Meet”,让企业高效协作的视频会议系统
    随着办公方式的多元化,数智化办公正在逐渐进入企事业单位。保持员工移动和远程高效工作的关键是为他们提供正确的协作工具以及最佳的连接性。高效的音视频会议系统成为办公的......
  • mybatis批量插入大量数据
    Mybatis内置的ExecutorType有3种,SIMPLE、REUSE、BATCH;默认的是simple,该模式下它为每个语句的执行创建一个新的预处理语句,单条提交sql;而batch模式重复使用已经预处理的语......