Mybatis【9】-- Mybatis占位符#{}和拼接符${}有什么區(qū)別?

代碼直接放在Github倉(cāng)庫(kù)【https://github.com/Damaer/Mybatis-Learning 】,可直接運(yùn)行,就不占篇幅了。

[TOC]

1.#{}占位符

1.#{}占位符可以用來(lái)設(shè)置參數(shù),如果傳進(jìn)來(lái)的是基本類型,也就是(string,long,double,int,boolean,float等),那么#{}里面的變量名可以隨意寫(xiě),什么abc,xxx等等,這個(gè)名字和傳進(jìn)來(lái)的參數(shù)名可以不一致。

2.如果傳進(jìn)來(lái)的是pojo類型,那么#{}中的變量名必須是pojo的屬性名,可以寫(xiě)成屬性名,也可以寫(xiě)屬性名.屬性名。

參數(shù)是int,不需要設(shè)置parameterType

<delete id="deleteStudentById" >
    delete from student where id=#{XXXdoukeyi}
</delete>

parameterTypepojo類,如果使用pojo類型作為參數(shù),那么必須提供get方法,也就是框架在運(yùn)行的時(shí)候需要通過(guò)反射根據(jù)#{}中的名字,拿到這個(gè)值放到sql語(yǔ)句中,如果占位符中的名稱和屬性不一致,那么報(bào)ReflectionException

<insert id="insertStudent" parameterType="Student">
    insert into student(name,age,score) values(#{name},#{age},#{score})
</insert>

3.#{}占位符不能解決的三類問(wèn)題:

動(dòng)態(tài)表名不可以用#{} :Select * from #{table}
動(dòng)態(tài)列名不可以用#{} : select #{column} from table
動(dòng)態(tài)排序列不可以用#{} : select * from table order by #{column}

注意:不能這樣寫(xiě):

<insert id="insertStudent" parameterType="Student">
    insert into student(name,age,score) values(#{Student.name},#{Student.age},#{Student.score})
</insert>

否則會(huì)報(bào)一個(gè)錯(cuò)誤(會(huì)將Student當(dāng)成一個(gè)屬性),所以我們類名就直接省略不寫(xiě)就可以了:

### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'Student' in 'class bean.Student'

2.${}拼接符

1.如果傳進(jìn)來(lái)的是基本類型,也就是(string,long,double,int,boolean,float等),那么#{}里面的變量名必須寫(xiě)value。

<delete id="deleteStudentById" >
    delete from student where id=${value}
</delete>

2.如果傳進(jìn)來(lái)的是pojo類型,那么#{}中的變量名必須是pojo的屬性名,可以寫(xiě)成屬性名,也可以寫(xiě)屬性名.屬性名但是由于是拼接的方式,對(duì)于字符串我們需要自己加引號(hào)。

<insert id="insertStudent" parameterType="Student">
    insert into student(name,age,score) values('${name}',${age},${score})
</insert>

與上面一樣,不能將類名寫(xiě)進(jìn)來(lái):

<!--這是錯(cuò)誤的-->
<insert id="insertStudent" parameterType="Student">
    insert into student(name,age,score) values('${Student.name}',${Student.age},${Student.score})
</insert>

3.${}占位符是字符串連接符,可以用來(lái)動(dòng)態(tài)設(shè)置表名,列名,排序名

動(dòng)態(tài)表名 :Select * from {table} 動(dòng)態(tài)列名 : select{column} from table
動(dòng)態(tài)排序 : select * from table order by ${column}

4.${}可以作為連接符使用,但是這樣的方式是不安全的,很容易發(fā)生sql注入問(wèn)題,sql注入問(wèn)題可以參考https://blog.csdn.net/aphysia/article/details/80465600

<select id="selectStudentsByName" resultType="Student">
    select id,name,age,score from student where name like '%${value}%'
</select>

3.#{}與${}區(qū)別

  • 1.能使用#{}的時(shí)候盡量使用#{},不使用${}。
  • 2.#{}相當(dāng)于jdbc中的preparedstatement(預(yù)編譯),${}是直接使用里面的值進(jìn)行拼接,如果解釋預(yù)編譯和直接拼接,我想可以這么理解預(yù)編譯:比如將一個(gè)#{name}傳進(jìn)來(lái),預(yù)編譯是先將sql語(yǔ)句編譯成為模板,也就是我知道你要干什么,假設(shè)這個(gè)sql是要查詢名字為xxx的學(xué)生信息,那無(wú)論這個(gè)xxx里面是什么信息,我都只會(huì)去根據(jù)名字這一列查詢,里面無(wú)論寫(xiě)的是什么,都只會(huì)當(dāng)做一個(gè)字符串,這個(gè)類型在預(yù)編譯的時(shí)候已經(jīng)定義好了。
  • 3.${}就不一樣,是將語(yǔ)句拼接之后才確定查詢條件/類型的,那么就會(huì)有被注入的可能性,有些人故意將名字設(shè)置為刪除條件,這時(shí)候sql就變成刪除操作了。
  • 所以我們一般類似模糊查詢都是用#{}拼接
<select id="selectStudentsByName" resultType="Student">
    select id,name,age,score from student where name like '%' #{name} '%'
</select>
  • 但是對(duì)于order by 我們是用不了#{}的,因?yàn)橛昧诉@個(gè)就會(huì)被自動(dòng)轉(zhuǎn)換成字符串,自動(dòng)加引號(hào),這樣語(yǔ)句就不生效了。
<select id="selectStudentsByName" resultType="Student">
    select id,name,age,score from student order by #{column}
</select>

<!--編譯出來(lái)的結(jié)果如下:-->
select * from table order by 'column'

那我們需要怎么處理呢?我們只能使用${},MyBatis不會(huì)修改或轉(zhuǎn)義字符串。這樣是不安全的,會(huì)導(dǎo)致潛在的SQL注入攻擊,我們需要自己限制,不允許用戶輸入這些字段,或者通常自行轉(zhuǎn)義并檢查。所以這必須過(guò)濾輸入的內(nèi)容。

【作者簡(jiǎn)介】
秦懷,公眾號(hào)【秦懷雜貨店】作者,技術(shù)之路不在一時(shí),山高水長(zhǎng),縱使緩慢,馳而不息。這個(gè)世界希望一切都很快,更快,但是我希望自己能走好每一步,寫(xiě)好每一篇文章,期待和你們一起交流。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容