mybatis 獲取執(zhí)行sql 輪子

mybatis工具類

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class MybatisBack {
    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();

    /**
     * 通過接口獲取sql
     *
     * @param mapper
     * @param methodName
     * @param args
     * @return
     */
    public static String getMapperSql(Object mapper, String methodName, Object... args) {
        MetaObject metaObject = SystemMetaObject.forObject(mapper);
        SqlSession session = (SqlSession) metaObject.getValue("h.sqlSession");
        Class mapperInterface = (Class) metaObject.getValue("h.mapperInterface");
        String fullMethodName = mapperInterface.getCanonicalName() + "." + methodName;
        if (args == null || args.length == 0) {
            return getNamespaceSql(session, fullMethodName, null);
        } else {
            return getMapperSql(session, mapperInterface, methodName, args);
        }
    }

    /**
     * 通過Mapper方法名獲取sql
     *
     * @param session
     * @param fullMapperMethodName
     * @param args
     * @return
     */
    public static String getMapperSql(SqlSession session, String fullMapperMethodName, Object... args) {
        if (args == null || args.length == 0) {
            return getNamespaceSql(session, fullMapperMethodName, null);
        }
        String methodName = fullMapperMethodName.substring(fullMapperMethodName.lastIndexOf('.') + 1);
        Class mapperInterface = null;
        try {
            mapperInterface = Class.forName(fullMapperMethodName.substring(0, fullMapperMethodName.lastIndexOf('.')));
            return getMapperSql(session, mapperInterface, methodName, args);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("參數(shù)" + fullMapperMethodName + "無效!");
        }
    }

    /**
     * 通過Mapper接口和方法名
     *
     * @param session
     * @param mapperInterface
     * @param methodName
     * @param args
     * @return
     */
    public static String getMapperSql(SqlSession session, Class mapperInterface, String methodName, Object... args) {
        String fullMapperMethodName = mapperInterface.getCanonicalName() + "." + methodName;
        if (args == null || args.length == 0) {
            return getNamespaceSql(session, fullMapperMethodName, null);
        }
        Method method = getDeclaredMethods(mapperInterface, methodName);
        Map params = new HashMap();
        final Class<?>[] argTypes = method.getParameterTypes();
        for (int i = 0; i < argTypes.length; i++) {
            if (!RowBounds.class.isAssignableFrom(argTypes[i]) && !ResultHandler.class.isAssignableFrom(argTypes[i])) {
                String paramName = "param" + String.valueOf(params.size() + 1);
                paramName = getParamNameFromAnnotation(method, i, paramName);
                params.put(paramName, i >= args.length ? null : args[i]);
            }
        }
        if (args != null && args.length == 1) {
            Object _params = wrapCollection(args[0]);
            if (_params instanceof Map) {
                params.putAll((Map) _params);
            }
        }
        return getNamespaceSql(session, fullMapperMethodName, params);
    }


    /**
     * 通過命名空間方式獲取sql
     *
     * @param session
     * @param namespace
     * @return
     */
    public static String getNamespaceSql(SqlSession session, String namespace) {
        return getNamespaceSql(session, namespace, null);
    }

    /**
     * 通過命名空間方式獲取sql
     *
     * @param session
     * @param namespace
     * @param params
     * @return
     */
    public static String getNamespaceSql(SqlSession session, String namespace, Object params) {
        params = wrapCollection(params);
        Configuration configuration = session.getConfiguration();
        MappedStatement mappedStatement = configuration.getMappedStatement(namespace);
        TypeHandlerRegistry typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
        BoundSql boundSql = mappedStatement.getBoundSql(params);
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        String sql = boundSql.getSql();
        if (parameterMappings != null) {
            for (int i = 0; i < parameterMappings.size(); i++) {
                ParameterMapping parameterMapping = parameterMappings.get(i);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    Object value;
                    String propertyName = parameterMapping.getProperty();
                    if (boundSql.hasAdditionalParameter(propertyName)) {
                        value = boundSql.getAdditionalParameter(propertyName);
                    } else if (params == null) {
                        value = null;
                    } else if (typeHandlerRegistry.hasTypeHandler(params.getClass())) {
                        value = params;
                    } else {
                        MetaObject metaObject = configuration.newMetaObject(params);
                        value = metaObject.getValue(propertyName);
                    }
                    JdbcType jdbcType = parameterMapping.getJdbcType();
                    if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull();
                    sql = replaceParameter(sql, value, jdbcType, parameterMapping.getJavaType());
                }
            }
        }
        return sql;
    }

    /**
     * 根據(jù)類型替換參數(shù)
     * 僅作為數(shù)字和字符串兩種類型進(jìn)行處理,需要特殊處理的可以繼續(xù)完善這里
     *
     * @param sql
     * @param value
     * @param jdbcType
     * @param javaType
     * @return
     */
    private static String replaceParameter(String sql, Object value, JdbcType jdbcType, Class javaType) {
        String strValue = String.valueOf(value);
        if (jdbcType != null) {
            switch (jdbcType) {
                //數(shù)字
                case BIT:
                case TINYINT:
                case SMALLINT:
                case INTEGER:
                case BIGINT:
                case FLOAT:
                case REAL:
                case DOUBLE:
                case NUMERIC:
                case DECIMAL:
                    break;
                //日期
                case DATE:
                case TIME:
                case TIMESTAMP:
                    //其他,包含字符串和其他特殊類型
                default:
                    strValue = "'" + strValue + "'";


            }
        } else if (Number.class.isAssignableFrom(javaType)) {
            //不加單引號
        } else {
            strValue = "'" + strValue + "'";
        }
        return sql.replaceFirst("\\?", strValue);
    }

    /**
     * 獲取指定的方法
     *
     * @param clazz
     * @param methodName
     * @return
     */
    private static Method getDeclaredMethods(Class clazz, String methodName) {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                return method;
            }
        }
        throw new IllegalArgumentException("方法" + methodName + "不存在!");
    }

    /**
     * 獲取參數(shù)注解名
     *
     * @param method
     * @param i
     * @param paramName
     * @return
     */
    private static String getParamNameFromAnnotation(Method method, int i, String paramName) {
        final Object[] paramAnnos = method.getParameterAnnotations()[i];
        for (Object paramAnno : paramAnnos) {
            if (paramAnno instanceof Param) {
                paramName = ((Param) paramAnno).value();
            }
        }
        return paramName;
    }

    /**
     * 簡單包裝參數(shù)
     *
     * @param object
     * @return
     */
    private static Object wrapCollection(final Object object) {
        if (object instanceof List) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("list", object);
            return map;
        } else if (object != null && object.getClass().isArray()) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("array", object);
            return map;
        }
        return object;
    }
}

#自定義注解類
···
package com.hzxx.util;

import org.apache.poi.ss.formula.functions.T;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.Order;

import java.lang.annotation.*;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Project Name: fjgl_server
 * File Name: Delroolback
 * Package Name: com.hzxx.util
 * Date: 2021/10/11 10:15
 * Copyright (c) 2021,All Rights Reserved.
 */

@Target({ElementType.METHOD})//
@Retention(RetentionPolicy.RUNTIME) // 注解會在class字節(jié)碼文件中存在,在運(yùn)行時可以通過反射獲取到
@Documented//說明該注解將被包含在javadoc中


@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface Delroolback {
    //String參數(shù)類型 behaviorDes代表調(diào)用參數(shù) behaviorDes("參數(shù)") default默認(rèn)參數(shù)
    String jsonbean() default "";
}

#注解實現(xiàn)類
package com.hzxx.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hzxx.enitybus.entity.SysUser;
import com.hzxx.fullback.FullBack;
import com.hzxx.fullback.FullbackDao;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.TypeVariable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSON;


/**
 * Project Name: fjgl_server
 * File Name: DelroolBackAnalytic
 * Package Name: com.hzxx.util
 * Date: 2021/10/11 10:27
 * Copyright (c) 2021,All Rights Reserved.
 */


@Aspect   //表明為切面類
@Component
public class DelroolBackAnalytic {


    @Resource
    FullbackDao fullbackDao;


    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Resource
    MybatisBack mybatisBack;


    @Autowired
    private ApplicationContext applicationContext;


    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();


    @Pointcut("@annotation(com.hzxx.util.Delroolback)")
    private void pointcut() {}

/**
 * 其中@Pointcut聲明了切點(diǎn)(這里的切點(diǎn)是我們自定義的注解類),
 * @Before聲明了通知內(nèi)容,在具體的通知中,我們通過@annotation(delroolback)拿到了自定義的注解對象,
 * */
    @Before("pointcut() && @annotation(delroolback)")
    public void Delroolback(final JoinPoint joinPoint,Delroolback delroolback) {
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Delroolback annotation = signature.getMethod().getAnnotation(Delroolback.class);
            String bean = getAnnotationValue(joinPoint, annotation.jsonbean());
            FullBack bask =JSONObject.parseObject(bean, FullBack.class);
            //傳入的參數(shù)
            Map<String,Object> map =JSON.parseObject(bask.getJson(),Map.class);
//            //類名
//            String clsName=joinPoint.getSignature().getDeclaringType().getSimpleName();
//            //方法名
//            String modName= joinPoint.getSignature().getName();

           //獲取mybatis執(zhí)行的sql
            String mapperSql = mybatisBack.getMapperSql(
                    applicationContext.getBean(bask.getLetname()),
                    bask.getWay(),
                    map);
            //保存至臨時表
           do someting...

        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public String getAnnotationValue(JoinPoint joinPoint, String name) {
        String paramName = name;
        // 獲取方法中所有的參數(shù)
        Map<String, Object> params = getParams(joinPoint);
        // 參數(shù)是否是動態(tài)的:#{paramName}
        if (paramName.matches("^#\\{\\D*\\}")) {
            // 獲取參數(shù)名
            paramName = paramName.replace("#{", "").replace("}", "");
            // 是否是復(fù)雜的參數(shù)類型:對象.參數(shù)名
            if (paramName.contains(".")) {
                String[] split = paramName.split("\\.");
                // 獲取方法中對象的內(nèi)容
                Object object = getValue(params, split[0]);
                // 轉(zhuǎn)換為JsonObject
                JSONObject jsonObject=(JSONObject) JSONObject.toJSON(object);
                // 獲取值
                Object o = jsonObject.get(split[1]);
                return String.valueOf(o);
            }
            // 簡單的動態(tài)參數(shù)直接返回
            return String.valueOf(getValue(params, paramName));
        }
        // 非動態(tài)參數(shù)直接返回
        return name;
    }

    /**
     * 根據(jù)參數(shù)名返回對應(yīng)的值
     *
     * @param map
     * @param paramName
     * @return
     */
    public Object getValue(Map<String, Object> map, String paramName) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getKey().equals(paramName)) {
                return entry.getValue();
            }
        }
        return null;
    }

    /**
     * 獲取方法的參數(shù)名和值
     *
     * @param joinPoint
     * @return
     */
    public Map<String, Object> getParams(JoinPoint joinPoint) {
        Map<String, Object> params = new HashMap<>(8);
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String[] names = signature.getParameterNames();
        for (int i = 0; i < args.length; i++) {
            params.put(names[i], args[i]);
        }
        return params;
    }






    @Pointcut("@annotation(com.hzxx.util.Delroolback)")
    public void test() {}


//    //在事件通知類型中申明returning即可獲取返回值
//    @AfterReturning(value = "test()", returning="returnValue")
//    public void logMethodCall(JoinPoint jp, Object returnValue) throws Throwable {
//        System.out.println("進(jìn)入后置增強(qiáng)了!");
//        String name = jp.getSignature().getName();
//        System.out.println(name);
//        System.out.println("方法返回值為:" + returnValue);
//    }


}



##調(diào)用方式
fl為傳入?yún)?shù) 為json或string
 @Delroolback(jsonbean="#{fl}")
    public void delsa(String fl){}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容