MyBatis動態傳入表名


mybatis里#{}與${}的用法:

  在動態sql解析過程,#{}與${}的效果是不一樣的:

  #{ } 解析為一個 JDBC 預編譯語句(prepared statement)的參數標記符。

  如以下sql語句

  select * from user where name = #{name};

  會被解析為:

  select * from user where name = ?;

  可以看到#{}被解析為一個參數占位符?。

 

  ${ } 僅僅為一個純碎的 string 替換,在動態 SQL 解析階段將會進行變量替換

  如以下sql語句:

  select * from user where name = ${name};

  當我們傳遞參數“sprite”時,sql會解析為:

  select * from user where name = "sprite";

  可以看到預編譯之前的sql語句已經不包含變量name了。

  綜上所得, ${ } 的變量的替換階段是在動態 SQL 解析階段,而 #{ }的變量的替換是在 DBMS 中。

#{}與${}的區別可以簡單總結如下:

  • #{}將傳入的參數當成一個字符串,會給傳入的參數加一個雙引號
  • ${}將傳入的參數直接顯示生成在sql中,不會添加引號
  • #{}能夠很大程度上防止sql注入,${}無法防止sql注入

  ${}在預編譯之前已經被變量替換了,這會存在sql注入的風險。如下sql

  select * from ${tableName} where name = ${name}

  如果傳入的參數tableName為user; delete user; --,那么sql動態解析之后,預編譯之前的sql將變為:

  select * from user; delete user; -- where name = ?;

  --之后的語句將作為注釋不起作用,頓時我和我的小伙伴驚呆了!!!看到沒,本來的查詢語句,竟然偷偷的包含了一個刪除表數據的sql,是刪除,刪除,刪除!!!重要的事情說三遍,可想而知,這個風險是有多大。

  • ${}一般用於傳輸數據庫的表名、字段名等
  • 能用#{}的地方盡量別用${}

  進入正題,通過上面的分析,相信大家可能已經對如何動態調用表名和字段名有些思路了。示例如下:

  <select id="getUser" resultType="java.util.Map" parameterType="java.lang.String" statementType="STATEMENT">
    select 
         ${columns}
    from ${tableName}
        where 
        COMPANY_REMARK = ${company} </select>

  要實現動態調用表名和字段名,就不能使用預編譯了,需添加statementType="STATEMENT"" 。

  statementType:STATEMENT(非預編譯),PREPARED(預編譯)或CALLABLE中的任意一個,這就告訴 MyBatis 分別使用Statement,PreparedStatement或者CallableStatement。默認:PREPARED。這里顯然不能使用預編譯,要改成非預編譯。

  其次,sql里的變量取值是${xxx},不是#{xxx}。

  因為${}是將傳入的參數直接顯示生成sql,如${xxx}傳入的參數為字符串數據,需在參數傳入前加上引號,如:

   String name = "sprite";
   name = "'" + name + "'";

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM