成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

解析Mybatis Porxy動(dòng)態(tài)代理和sql解析替換問題

瀏覽:2日期:2023-10-19 12:44:10
JDK常用核心原理概述

在 Mybatis 中,常用的作用就是講數(shù)據(jù)庫中的表的字段映射為對(duì)象的屬性,在進(jìn)入Mybatis之前,原生的 JDBC 有幾個(gè)步驟:導(dǎo)入 JDBC 驅(qū)動(dòng)包,通過 DriverManager 注冊(cè)驅(qū)動(dòng),創(chuàng)建連接,創(chuàng)建 Statement,增刪改查,操作結(jié)果集,關(guān)閉連接

過程詳解

首先進(jìn)行類的加載,通過 DriverManager 注冊(cè)驅(qū)動(dòng)

Class.forName('com.mysql.jdbc.Driver');Connection connection = DriverManager.getConnection('');

為什么在這里可以直接注冊(cè)進(jìn)去,com.mysql.jdbc.Driver 被加載到 Driver.class ,在 DriverManager 中,首先有一個(gè)靜態(tài)代碼塊來進(jìn)行初始化加載 Driver

static { loadInitialDrivers(); println('JDBC DriverManager initialized');}

通過 loadInitialDrivers(),來加載 Driver,拿出 jdbc.drivers,通過 ServiceLoader 讀取 Driver.class,讀取拿出 driver 和 所有迭代器,一直迭代

private static void loadInitialDrivers() { String drivers; // 訪問修飾符,在這里把 jdbc.drivers 拿出來 try {drivers = AccessController.doPrivileged(new PrivilegedAction<String>() { public String run() {return System.getProperty('jdbc.drivers'); }}); } catch (Exception ex) {drivers = null; } AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() { // 讀取拿出 driver 和 所有迭代器 ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class); Iterator<Driver> driversIterator = loadedDrivers.iterator();// 一直進(jìn)行迭代 try{while(driversIterator.hasNext()) { driversIterator.next();} } catch(Throwable t) { // Do nothing } return null;} }); println('DriverManager.initialize: jdbc.drivers = ' + drivers); if (drivers == null || drivers.equals('')) {return; } String[] driversList = drivers.split(':'); println('number of Drivers:' + driversList.length); for (String aDriver : driversList) {try { println('DriverManager.Initialize: loading ' + aDriver); Class.forName(aDriver, true, ClassLoader.getSystemClassLoader());} catch (Exception ex) { println('DriverManager.Initialize: load failed: ' + ex);} }}

從 Driver 加載完后,就可以得到一個(gè)和數(shù)據(jù)庫的連接 connection ,connection 就可以創(chuàng)建一個(gè) Statement,Statement 就可以進(jìn)行執(zhí)行 sql 語句,將結(jié)果返回一個(gè)結(jié)果集,獲取出來的結(jié)果集遍歷放進(jìn)一個(gè) List 集合中

Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery('select * from mybatis.user'); while (resultSet.next()) { int id = resultSet.getInt(1); String username = resultSet.getString(2); list.add(new User(id,username));}

在原生的 JDBC 直接操作中,繁雜的步驟在業(yè)務(wù)代碼中不會(huì)使用,而 Mybatis 可以在更好的便利度上使用

JDK動(dòng)態(tài)代理sql語句解析替換

在 JDK 動(dòng)態(tài)代理中,利用了 Proxy 這個(gè)類來實(shí)現(xiàn),在 Proxy 中,有著 newProxyInstance() 方法,創(chuàng)建一個(gè)動(dòng)態(tài)代理實(shí)例

interface UserMapper { @Select('select * from mybatis.user where id =#{id}') List<User> selectUserList();}public static void main(String[] args) { UserMapper userMapper = (UserMapper) Proxy.newProxyInstance( JDKMybatis.class.getClassLoader(), new Class<?>[]{UserMapper.class}, new InvocationHandler() { /** * 在 invoke() 方法中就可以進(jìn)行查找 method,args * @param proxy 動(dòng)態(tài)代理 * @param method 方法 * @param args 參數(shù) */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 把注解類獲取,可以查出注解的值等多種其他值Select annotation = method.getAnnotation(Select.class);if (annotation != null) { String[] value = annotation.value(); System.out.println(Arrays.toString(value));}return null; } }); userMapper.selectUserList(1);}

newProxyInstance() 的創(chuàng)建需要三個(gè)參數(shù),查看源碼,可以知道需要 ClassLoader 類加載器,interfaces 接口(Mapper 接口),InvocationHandler 處理器,來進(jìn)行處理

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

解析Mybatis Porxy動(dòng)態(tài)代理和sql解析替換問題

把 sql 語句中的參數(shù)取出來放進(jìn) args,這時(shí)需要一個(gè) Map 來進(jìn)行傳值問題當(dāng)在通過反射獲取方法的參數(shù)名,method.getParameters() 獲取出來的參數(shù)都是 arg0,arg1...無意義參數(shù)

解析Mybatis Porxy動(dòng)態(tài)代理和sql解析替換問題

在Java8之前,代碼編譯為class文件后,方法參數(shù)的類型是固定的,但參數(shù)名稱卻丟失了,在編譯的時(shí)候,需要有編譯的選項(xiàng),javac -parameters 默認(rèn)是關(guān)閉的,需要在 idea 中設(shè)置開啟,開啟完成后,重新編譯源文件

解析Mybatis Porxy動(dòng)態(tài)代理和sql解析替換問題

這種方式只能臨時(shí)解決當(dāng)前環(huán)境設(shè)置,在其他人運(yùn)行代碼時(shí)還是要重新設(shè)置另一種解決方式,在pom文件中添加編譯參數(shù):

<plugins> <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration> <compilerArgument>-parameters</compilerArgument> <source>1.8</source> <target>1.8</target></configuration> </plugin></plugins>

編譯完成后,重新執(zhí)行,再次通過method.getParameters()獲取參數(shù):

解析Mybatis Porxy動(dòng)態(tài)代理和sql解析替換問題

解析原來的 sql ,就要把 #{} 給替換掉,這時(shí)候可以使用 StringBuffer 類來實(shí)現(xiàn)替換

private static String parseSql(String sql, Map<String, Object> argsNameMap) { // 定義為常量數(shù)組 char[] str = {’#’, ’{’}; StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < sql.length(); i++) { char aloneParseSql = sql.charAt(i); if (str[0] == aloneParseSql) { int nextIndex = i + 1; char nextChar = sql.charAt(nextIndex); // # 后應(yīng)該是 { ,不匹配直接拋出異常 if (str[1] != nextChar) {throw new RuntimeException(String.format( '此處應(yīng)該是:#{n sql:%sn index:%d', stringBuilder.toString(), nextIndex)); } /*1 已經(jīng)解析完的下標(biāo)2 解析完的 #{} 內(nèi)的參數(shù)名3 把對(duì)應(yīng)的 argsName 的值 argsValue 取出來4 追加到原來的 stringBuilder 中的 sql 語句后面 */ StringBuilder partStringBuilder = new StringBuilder(); i = partParseSql(partStringBuilder, sql, nextIndex); String argsName = partStringBuilder.toString(); Object argsValue = argsNameMap.get(argsName); stringBuilder.append(argsValue.toString()); } // 如果沒有條件,直接追加 stringBuilder.append(aloneParseSql); } return stringBuilder.toString();}

在其中需要把需要替換的值,再用 StringBuffer 類來實(shí)現(xiàn)

private static int partParseSql(StringBuilder partStringBuilder, String sql, int nextIndex) { // 由于 nextIndex 當(dāng)前指針指向的是 { 所以要加一位,把后面內(nèi)容解析 nextIndex++; char[] str = {’}’}; for (; nextIndex < sql.length(); nextIndex++) { char indexSql = sql.charAt(nextIndex); if (str[0] != indexSql) { partStringBuilder.append(indexSql); } if (str[0] == indexSql) { return nextIndex; } } throw new RuntimeException(String.format( '缺少:}n index:%d', nextIndex));}

再重新在 invoke 方法中進(jìn)行調(diào)用,完成 sql 語句的動(dòng)態(tài)拼裝

@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 把注解類獲取,可以查出注解的值等多種其他值 Select annotation = method.getAnnotation(Select.class); Map<String, Object> argsNameMap = MapBuildArgsName(method, args); if (annotation != null) { String[] value = annotation.value(); String sql = value[0]; sql = parseSql(sql, argsNameMap); System.out.println(sql); } return null;}

解析Mybatis Porxy動(dòng)態(tài)代理和sql解析替換問題

到此這篇關(guān)于Mybatis(一)Porxy動(dòng)態(tài)代理和sql解析替換的文章就介紹到這了,更多相關(guān)Mybatis(一)Porxy動(dòng)態(tài)代理和sql解析替換內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Mybatis 數(shù)據(jù)庫
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
综合在线观看色| 久久资源在线| 久久婷婷丁香| 亚洲精品综合在线| 亚洲夜间福利| 欧美激情中文不卡| 色综合天天综合色综合av| 2020国产精品| 91麻豆免费观看| 久久中文字幕电影| 国产精品自拍三区| 欧美浪妇xxxx高跟鞋交| 黑人巨大精品欧美黑白配亚洲| 欧美性大战久久久久久久 | 日韩欧美亚洲国产另类| 国产成人久久精品77777最新版本| 欧美军同video69gay| 日韩 欧美一区二区三区| 在线中文字幕一区| 久久精品99国产精品| 欧美日韩一区二区电影| 国产一区二区女| 91精选在线观看| 国产成人鲁色资源国产91色综 | 欧美午夜不卡| 国产精品日日摸夜夜摸av| 韩日在线一区| 一区二区免费在线播放| 久久久久国产精品一区二区 | 在线亚洲观看| 午夜伦欧美伦电影理论片| 欧美亚洲免费高清在线观看| 丝袜国产日韩另类美女| 色偷偷久久一区二区三区| 精品亚洲国内自在自线福利| 欧美一区二区三区视频在线| 99精品视频在线播放观看| 国产精品国产三级国产aⅴ入口| 亚洲精品在线视频观看| 性久久久久久久久久久久| 欧美少妇性性性| 成人久久18免费网站麻豆| 国产精品素人一区二区| 国产精品久久一区二区三区| 视频在线观看91| 欧美高清视频一二三区 | 噜噜噜噜噜久久久久久91 | 欧美二区三区91| 不卡一区二区在线| 国产精品久久久久影院亚瑟| 99国产精品私拍| 日韩精品每日更新| 欧美疯狂做受xxxx富婆| 99国产一区二区三精品乱码| 亚洲人成网站影音先锋播放| 久久综合图片| 成人va在线观看| 亚洲人成网站色在线观看| 色丁香久综合在线久综合在线观看| 国产精品一区二区无线| 日本一区二区成人| 久久综合网络一区二区| 国产成人三级在线观看| 久久一区欧美| 国模娜娜一区二区三区| 久久精品噜噜噜成人av农村| 日本中文字幕一区二区视频 | 日韩女优av电影在线观看| 欧美一区高清| 婷婷夜色潮精品综合在线| 日韩美女在线视频 | 噜噜噜躁狠狠躁狠狠精品视频 | www.欧美亚洲| 综合激情成人伊人| 久久一区精品| 99久久99久久免费精品蜜臀| 亚洲制服欧美中文字幕中文字幕| 欧美日韩高清影院| 欧美国产91| 天堂久久一区二区三区| 亚洲精品在线一区二区| 亚洲最黄网站| 国产一区二区精品久久91| 亚洲国产精品高清| 日本电影欧美片| av一区二区不卡| 亚洲mv大片欧洲mv大片精品| 久久综合丝袜日本网| 久久国产精品毛片| av一区二区不卡| 婷婷丁香久久五月婷婷| 欧美精品一区二区三区在线播放| 国产欧美日韩在线播放| 国产很黄免费观看久久| 亚洲女人的天堂| 91精品国产综合久久香蕉的特点 | 亚洲欧美成aⅴ人在线观看| 欧美日韩视频第一区| 国内精品国语自产拍在线观看| 麻豆精品在线播放| 日韩一区在线免费观看| 91精品国产品国语在线不卡| 亚洲精品在线观看免费| 成人精品国产福利| 日韩av在线播放中文字幕| 中文字幕一区三区| 91精品欧美福利在线观看| 99热精品在线观看| 福利91精品一区二区三区| 亚洲午夜激情av| 国产欧美精品区一区二区三区| 欧美日韩在线播放| 亚洲人www| www.66久久| 日韩国产欧美一区二区三区| 欧美激情中文字幕一区二区| 欧美福利电影网| 久久九九免费| 亚洲视频精品| 91在线观看成人| 国产米奇在线777精品观看| 亚洲一区二区视频| 欧美国产精品一区| 日韩三级免费观看| 91久久香蕉国产日韩欧美9色| 欧美日韩一区在线播放| 懂色一区二区三区免费观看| 日韩福利电影在线观看| 亚洲人吸女人奶水| 久久综合色鬼综合色| 欧美精品九九99久久| 亚洲专区一区二区三区| 国产精品v日韩精品v欧美精品网站| 国产福利91精品| 日本va欧美va精品发布| 一区二区三区日韩欧美精品| 亚洲国产岛国毛片在线| 日韩一区和二区| 91福利小视频| 欧美亚洲视频| 影音先锋久久久| 99久久久精品免费观看国产蜜| 毛片不卡一区二区| 亚洲一二三区视频在线观看| 中文字幕在线免费不卡| 国产视频一区在线播放| 日韩欧美国产1| 欧美日韩国产a| 色八戒一区二区三区| 亚洲女同同性videoxma| 99精品国产高清一区二区| 欧美欧美全黄| 91麻豆.com| 91亚洲精品久久久蜜桃| 国产成人8x视频一区二区| 狠狠色丁香婷综合久久| 美日韩一区二区| 免费看日韩a级影片| 日韩精品成人一区二区在线| 亚洲成人激情社区| 一区二区三区日韩欧美精品| 亚洲日本青草视频在线怡红院| 国产精品国产三级国产普通话三级| 国产欧美日韩不卡| 中文一区二区完整视频在线观看 | 黄色日韩三级电影| 精品一二三四在线| 久草精品在线观看| 韩国av一区二区三区四区| 狠狠色综合日日| 久久99精品久久久久久| 久久精品国产澳门| 免费在线观看日韩欧美| 精品一区二区三区在线播放视频| 久久99久久精品| 国产在线精品免费av| 国产九色精品成人porny | 99国产精品久久久久| 9人人澡人人爽人人精品| 国产激情视频一区二区在线观看| 国产做a爰片久久毛片| 国产剧情av麻豆香蕉精品| 国产成+人+日韩+欧美+亚洲| 国产99久久久国产精品| 成人丝袜18视频在线观看| 91视频一区二区三区| 国产一区二区三区自拍| 亚洲精品看片| 欧美一级播放| 在线观看免费一区| 5858s免费视频成人| 欧美成人aa大片| 国产精品午夜久久| 亚洲精品一二三区| 天天综合日日夜夜精品| 麻豆视频观看网址久久| 国产精品99久| 欧美一区不卡| 一本久道久久久| 在线亚洲一区二区|