Mybatis中#{}和${}的區別以及對sql注入、預編譯、jdbcType的說明
#{}和${}都可以獲取map中的值或者pojo物件屬性的值;
sql語句示例:
select * from tbl_employee where id=${id} and last_name=#{lastName}
Preparing: select * from tbl_employee where id=2 and last_name=?
#{}和${}的區別:
#{}:是以預編譯的形式,將引數設定到sql語句中;PreparedStatement;防止sql注入
${}:取出的值直接拼裝在sql語句中;會有安全問題;例如#{}只能取出表中引數位置的值,即id=#{},但如:from #{} 就會出錯,或者排序order by #{}也會出錯,此時,from或order by後面就需要使用${}來拼接字串;
所以#{}用來賦值${}用來拼接sql語句
大多情況下,我們去引數的值都應該去使用#{};
原生jdbc不支援佔位符的地方我們就可以使用${}進行取值
比如分表、排序。。。;按照年份分表拆分
select * from ${year}_salary where xxx;
select * from tbl_employee order by ${f_name} ${order}
#{}:更豐富的用法:
規定引數的一些規則:
javaType、 jdbcType、 mode(儲存過程)、 numericScale、
resultMap、 typeHandler、 jdbcTypeName、 expression(未來準備支援的功能);
jdbcType通常需要在某種特定的條件下被設定:
在我們資料為null的時候,有些資料庫可能不能識別mybatis對null的預設處理。比如Oracle(報錯);
JdbcType OTHER:無效的型別;因為mybatis對所有的null都對映的是原生Jdbc的OTHER型別,oracle不能正確處理;
由於全域性配置中:jdbcTypeForNull=OTHER;oracle不支援;兩種辦法
1、#{email,jdbcType=NULL};
2、全域性配置檔案中配置全域性變數:<settings><setting name="jdbcTypeForNull" value="NULL"/></settings>
sql注入
sql注入例項:
預編譯
又稱為預處理,是做些程式碼文字的替換工作。是整個編譯過程的最先做的工作;
處理#開頭的指令;
預處理過程掃描原始碼,對其進行初步的轉換,產生新的原始碼提供給編譯器。可見預處理過程先於編譯器對原始碼進行處理。
jdbcType
Java物件中的型別和資料庫中型別的對應:
mybatis包中對應的類時JdbcType.java,且是列舉型別
1 JDBC Type Java Type
2 CHAR String
3 VARCHAR String
4 LONGVARCHAR String
5 NUMERIC java.math.BigDecimal
6 DECIMAL java.math.BigDecimal
7 BIT boolean
8 BOOLEAN boolean
9 TINYINT byte
10 SMALLINT short
11 INTEGER INTEGER
12 BIGINT long
13 REAL float
14 FLOAT double
15 DOUBLE double
16 BINARY byte[]
17 VARBINARY byte[]
18 LONGVARBINARY byte[]
19 DATE java.sql.Date
20 TIME java.sql.Time
21 TIMESTAMP java.sql.Timestamp
22 CLOB Clob
23 BLOB Blob
24 ARRAY Array
25 DISTINCT mapping of underlying type
26 STRUCT Struct
27 REF Ref
28 DATALINK java.net.URL[color=red][/color]