Mybatis框架中是如何获取到SQL语句的,让我们一起来模拟一下吧
生活随笔
收集整理的這篇文章主要介紹了
Mybatis框架中是如何获取到SQL语句的,让我们一起来模拟一下吧
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文主要是通過代理和反射來模擬Mybatis此ORM框架是如何獲得SQL語句及相關參數等。當我們拿到這些東西,那么一切就變得很簡單啦,想做啥就做啥啦。
與君共勉😁
一、基礎知識
我們都知道Mybatis框架主要就是靠代理和反射來進行操作,那么對于動態代理,怎么都需要了解一點點哈。
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
newProxyInstance,方法有三個參數:
-
loader: 用哪個類加載器去加載代理對象
-
interfaces:動態代理類需要實現的接口
-
h:動態代理方法在執行時,會調用h里面的invoke方法去執行
二、代碼
一個User類 為了測試加上的。
public class User {private Integer id;private String username;private String password; }具體代碼哦:加一下 Mybatis 的依賴就 可以直接copy測試啦哦
import org.apache.ibatis.annotations.Select; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map;/*** @Author: crush* @Date: 2021-05-27 11:32* version 1.0*/ interface UserMapper {/*** @return*/@Select("select * from user where id=#{id} and name=#{name}")List<User> selectUser(Integer id,String name); }/*** @author crush*/ public class Application {public static void main(String[] args) {// newProxyInstance 這里用的是jdk的代理UserMapper userMapper = (UserMapper) Proxy.newProxyInstance(Application.class.getClassLoader(), new Class[]{UserMapper.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("參數==> " + Arrays.toString(args));System.out.println("UserMapper執行的方法名==> " + method.getName());Map<String, Object> nameArgMap = buildMethodArgNameMap(method, args);System.out.println("方法上的參數名==> "+nameArgMap.toString());// 這咯是通過反射獲取方法上的注解Select annotation = method.getAnnotation(Select.class);if (annotation != null) {// 這里是獲取 注解的值String[] value = annotation.value();String sql = value[0];//解析sql 語句sql = parseSQL(sql, nameArgMap );System.out.println(sql);System.out.println("返回的類型==>"+method.getReturnType());System.out.println("返回的泛型==>"+method.getGenericReturnType());}return null;}});userMapper.selectUser(1,"crush");}public static String parseSQL(String sql, Map<String, Object> nameArgMap ) {StringBuilder stringBuilder = new StringBuilder();int length = sql.length();for (int i = 0; i < length; i++) {char c = sql.charAt(i);// 此處是判斷'#{'if (c == '#') {int nextIndex = i + 1;char nextChar = sql.charAt(nextIndex);if (nextChar != '{') {throw new RuntimeException(String.format("這里應該為#{\nsql:%s\nindex:%d",stringBuilder.toString(), nextIndex));}StringBuilder argSB = new StringBuilder();//此處是 讓argSB 獲取到 #{} 中的值 手動打印一下查看i = parseSQLArg(argSB, sql, nextIndex);String argName = argSB.toString();Object argValue = nameArgMap.get(argName);stringBuilder.append(argValue.toString());continue;}stringBuilder.append(c);}return stringBuilder.toString();}private static int parseSQLArg(StringBuilder argSB, String sql, int nextIndex) {nextIndex++;for (; nextIndex < sql.length(); nextIndex++) {char c = sql.charAt(nextIndex);if (c != '}') {argSB.append(c);continue;}if (c == '}') {return nextIndex;}}throw new RuntimeException(String.format("缺少右括號\nindex:%d", nextIndex));}public static Map<String, Object> buildMethodArgNameMap(Method method, Object[] args) {Map<String, Object> nameArgMap = new HashMap<String, Object>();Parameter[] parameters = method.getParameters();int[] index = {0};Arrays.asList(parameters).forEach(parameter -> {String name = parameter.getName();System.out.println("接口方法上參數名字==》"+name);nameArgMap.put(name, args[index[0]]);index[0]++;});return nameArgMap;} }自言自語
之前只是學習和使用mybatis,知道是代理和反射實現的框架原理,但是從來沒有真正去了解??催^之后發現,學習帶有好奇心,做什么都會有激情,事半功倍哦。
加油哦。
總結
以上是生活随笔為你收集整理的Mybatis框架中是如何获取到SQL语句的,让我们一起来模拟一下吧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 史上最详细阿里云服务器上Docker部署
- 下一篇: 绝对是最实用 PostMan测试进阶操作