1. 程式人生 > >(九)Mybatis的#{}佔位符和${}拼接符的區別

(九)Mybatis的#{}佔位符和${}拼接符的區別

注:程式碼已託管在GitHub上,地址是:https://github.com/Damaer/Mybatis-Learning,專案是mybatis-05-CURD,需要自取,需要配置maven環境以及mysql環境,覺得有用可以點個小星星,小菜鳥在此Thanks~

1.#{}佔位符

1.#{}佔位符可以用來設定引數,如果傳進來的是基本型別,也就是(string,long,double,int,boolean,float等),那麼#{}裡面的變數名可以隨意寫,什麼abc,xxx等等,這個名字和傳進來的引數名可以不一致。
2.如果傳進來的是pojo型別,那麼#{}中的變數名必須是pojo的屬性名,可以寫成屬性名

,也可以寫屬性名.屬性名
引數是int,不需要設定parameterType:

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

parameterType是pojo類,如果使用pojo型別作為引數,那麼必須提供get方法,也就是框架在執行的時候需要通過反射根據#{}中的名字,拿到這個值放到sql語句中,如果佔位符中的名稱和屬性不一致,那麼報ReflectionException。

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

3.注意:#{}佔位符不能解決三類問題

動態表名不可以用#{} :Select * from #{table}
動態列名不可以用#{} : select #{column} from table
動態排序列不可以用#{} : select * from table order by #{column}

注意:不能這樣寫:

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

否則會報一個錯誤(會將Student當成一個屬性),所以我們類名就直接省略不寫就可以了:

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

2.${}拼接符

1.如果傳進來的是基本型別,也就是(string,long,double,int,boolean,float等),那麼#{}裡面的變數名必須寫value。

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

2.如果傳進來的是pojo型別,那麼#{}中的變數名必須是pojo的屬性名,可以寫成屬性名,也可以寫屬性名.屬性名但是由於是拼接的方式,對於字串我們需要自己加引號

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

與上面一樣,不能將類名寫進來:

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

3.${}佔位符是字串連線符,可以用來動態設定表名,列名,排序名

動態表名 :Select * from t a b l e : s e l e c t {column} from table
動態排序 : select * from table order by c o l u m n 4. {}可以作為連線符使用,但是這樣的方式是不安全的,很容易發生sql注入問題,sql注入問題可以參考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.#{}與${}區別

  • 能使用#{}的時候儘量使用#{},不使用${}
  • #{}相當於jdbc中的preparedstatement(預編譯),${}是直接使用裡面的值進行拼接,如果解釋預編譯和直接拼接,我想可以這麼理解預編譯:比如將一個#{name}傳進來,預編譯是先將sql語句編譯成為模板,也就是我知道你要幹什麼,假設這個sql是要查詢名字為xxx的學生資訊,那無論這個xxx裡面是什麼資訊,我都只會去根據名字這一列查詢,裡面無論寫的是什麼,都只會當做一個字串,這個型別在預編譯的時候已經定義好了。
  • ${}就不一樣,是將語句拼接之後才確定查詢條件/型別的,那麼就會有被注入的可能性,有些人故意將名字設定為刪除條件,這時候sql就變成刪除操作了。
  • 所以我們一般類似模糊查詢都是用#{}拼接
<select id="selectStudentsByName" resultType="Student">
    select id,name,age,score from student where name like '%' #{name} '%'
</select>
  • 但是對於order by 我們是用不了#{}的,因為用了這個就會被自動轉換成字串,自動加引號,這樣語句就不生效了。
<select id="selectStudentsByName" resultType="Student">
    select id,name,age,score from student order by #{column}
</select>
<!--編譯出來的結果如下:-->
select * from table order by 'column'

那我們需要怎麼處理呢?我們只能使用${},MyBatis不會修改或轉義字串。這樣是不安全的,會導致潛在的SQL注入攻擊,我們需要自己限制,不允許使用者輸入這些欄位,或者通常自行轉義並檢查。所以這必須過濾輸入的內容。