- 1、數據類型匹配
- #:會進行預編譯,而且進行類型匹配(自動確定數據類型);
- $:不進行數據類型匹配。
- 2、實現方式:
- # 用於變量替換(先生成一個占位符,然后替換)
- select * from users where name = #name#
- 等效於
- prepareStement=stmt.createPrepareStement("select * from users where name = ?")
- prepareStement.setString (1,' 張三 ');
- $ 的作用實際上是字符串拼接()
- select * from users where name= $name$
- 等效於
- StringBuffer sb = newStringBuffer(256);
- sb.append("select * from userswhere name=").append(name);
- sb.toString();
- # 用於變量替換(先生成一個占位符,然后替換)
- 3、使用場景
- -#主要用於變量的傳遞。# 是用 prepareStement,提升效率。#方式一般用於傳入添加 / 修改的值或查詢 / 刪除的 where 條件
- $ 只是簡單的字符拼接而已,對於非變量部分, 只能使用 $。$ 方式一般用於傳入數據庫對象。例如傳入表名,select * from $tableName$ 對於不同的表執行統一的查詢
- 4、為什么會出現SQL注入?
- $沒有預編譯,只是字符串替換,所以語句可能被注入,傳給數據庫時是多條語句;
- 而#會先預編譯,驗證SQL語句,預防了問題的出現。
- 5、關於預編譯的理解:
- 為什么需要預編譯
- JDBC 中使用對象 PreparedStatement 來抽象預編譯語句,使用預編譯
- 預編譯階段可以優化 sql 的執行。
- 預編譯之后的 sql 多數情況下可以直接執行,DBMS 不需要再次編譯,越復雜的 sql,編譯的復雜度將越大,預編譯階段可以合並多次操作為一個操作。
- 預編譯語句對象可以重復利用。
- 把一個 sql 預編譯后產生的 PreparedStatement 對象緩存下來,下次對於同一個 sql,可以直接使用這個緩存的 PreparedState 對象。
- mybatis 默認情況下,將對所有的 sql 進行預編譯。
- 參考附錄:
- 說明下,就是$時傳給DBMS的時一個Statement對象,該對象會被DBMS先編譯后執行;
- 而#時傳給DBMS的時一個PrepareStatement 對象,該對象會直接傳給DBMS進行編譯,DBMS執行時會直接執行編譯后的語句。
- 為什么需要預編譯
- 6、參考:
- ibatis 中#和 $ 符號的區別 - geyouchao 的專欄 - CSDN 博客 https://blog.csdn.net/geyouchao/article/details/51817747
注:文章主體來源。 - Ibatis 的#和 $ 的區別 - Huangmoumou - 博客園 https://www.cnblogs.com/juanzila/p/8691860.html
- mybatis 之 # 與 $ 區別以及 sql 預編譯 - 每一步成長都與你分享 - CSDN 博客 https://blog.csdn.net/wo541075754/article/details/54292751
注:詳細解釋了預編譯,為什么要預編譯,以及SQL注入的問題。 - 什么是預編譯語句 - 網絡改變中國 - CSDN 博客 https://blog.csdn.net/hehe520347/article/details/8956750
注:對預編譯的詳細說明。
- ibatis 中#和 $ 符號的區別 - geyouchao 的專欄 - CSDN 博客 https://blog.csdn.net/geyouchao/article/details/51817747