手写一个MyBatis动态代理和参数解析

基础类:

package mybatis.annotations;

import java.lang.annotation.*;

/**
 * @Description: 
*

*
* @Author: Qz1997 * @create 2021/4/24 21:51 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Param { String value(); } package mybatis.annotations; import java.lang.annotation.*; /** * @Description:
*

*
* @Author: Qz1997 * @create 2021/4/24 21:51 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Select { String[] value(); } package mybatis.entity; /** * @Description:
*

*
* @Author: Qz1997 * @create 2021/4/24 21:51 */ public class User { private Integer id; private String name; private Integer age; }

主类:

package mybatis;

import mybatis.annotations.Param;
import mybatis.annotations.Select;
import mybatis.entity.User;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


interface UserMapping {
     
    @Select("select * form user where id = #{id} and  name = #{name} ")
    List<User> selectUserListByidAndName(@Param("id") Integer id, @Param("name") String name);
}


/**
 * @Description: 
* 解析Mapper借口 *

*
* @Author: Qz1997 * @create 2021/4/24 21:51 */ public class Main { public static void main(String[] args) { UserMapping userMapping = (UserMapping) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{ UserMapping.class}, (proxy, method, args1) -> { Map<String, Object> paramMap = bangdingParam(method, args1); Select annotation = method.getAnnotation(Select.class); if (annotation != null) { String originalSql = annotation.value()[0]; System.out.println("解析前的sql = " + originalSql); originalSql = bangdingParam(paramMap, originalSql); System.out.println("解析后的sql = " + originalSql); } Class<?> returnType = method.getReturnType(); System.out.println("返回值 类型 = " + returnType); Type genericReturnType = method.getGenericReturnType(); System.out.println("返回值 泛型类型 = " + genericReturnType); System.out.println("通过反射 解析 从数据库中查到结果 "); return null; }); userMapping.selectUserListByidAndName(1, "Test"); } /** * 替换原sql 参数 * * @param map 解析的参数 * @param originalSql 原来的sql * @return 新sql */ public static String bangdingParam(Map<String, Object> map, String originalSql) { StringBuilder sb = new StringBuilder(); int length = originalSql.length(); for (int i = 0; i < length; i++) { char indexChar = originalSql.charAt(i); if (indexChar == '#') { if (i + 1 >= length) { throw new RuntimeException(String.format("格式错讹误 原sql: %s index: %s", originalSql, i)); } if (originalSql.charAt(i + 1) != '{') { throw new RuntimeException(String.format("格式错讹误 没有 [{] 原sql: %s index: %s", originalSql, i)); } StringBuilder name = new StringBuilder(); i = parseSqlParam(originalSql, i + 1, name); if (name.toString().isEmpty()) { throw new RuntimeException("参数名错误"); } Object paramValue = map.get(name.toString()); sb.append(paramValue); continue; } sb.append(indexChar); } return sb.toString(); } /** * 解析参数名 * * @param originalSql 原sql * @param index 参数名开始的 `{` 下标 * @param paramName 参数名称 * @return 解析参数名结束下标 */ private static int parseSqlParam(String originalSql, int index, StringBuilder paramName) { int length = originalSql.length(); int newIndex = index; index++; for (; newIndex < length; newIndex++) { char indexChar = originalSql.charAt(newIndex); if (indexChar == '}') { paramName.append(originalSql, index, newIndex); return newIndex; } } throw new RuntimeException(String.format("格式错讹误 没有 [{] 原sql: %s ", originalSql)); } /** * 解析参数 * * @param method 执行的方法 * @param arg 传入的参数 * @return key参数名 value参数值 */ public static Map<String, Object> bangdingParam(Method method, Object[] arg) { Map<String, Object> map = new HashMap<>(16); int[] index = { 0}; Arrays.stream(method.getParameters()).forEach(parameter -> { String name = parameter.getAnnotation(Param.class).value(); if (String.class.equals(parameter.getType())) { map.put(name, "'" + arg[index[0]] + "'"); } // ..... // 其他类型处理 map.put(name, arg[index[0]]); index[0]++; }); return map; } }

结果
手写一个MyBatis动态代理和参数解析_第1张图片

你可能感兴趣的:(MyBatis,mybatis,java)