mybatis 預編譯

MyBatis預編譯

<select id="getUserById" resultMap="UserMap" parameterType="java.util.String">
    select 
        id,username,password,age,sex 
    from 
        t_user_info 
    where 
        id=#{id}
</select>

打印SQL

select 
    id,username,password,age,sex 
from 
    t_user_info 
where 
    id=?

MyBatis非預編譯

<select id="getUserById" resultMap="UserMap" parameterType="java.util.String">
    select 
        id,username,password,age,sex 
    from 
        t_user_info 
    where 
        id='${id}'
</select>

打印SQL

select 
    id,username,password,age,sex 
from 
    t_user_info 
where 
    id='1000001'

兩者實際執行執行SQL相同

select 
    id,username,password,age,sex 
from 
    t_user_info 
where 
    id='10000001'

SQL注入攻擊情況下(String id = "10000001' OR '1'='1";)

預編譯打印SQL,實際執行SQL

select 
    id,username,password,age,sex 
from 
    t_user_info 
where 
    id=?
​
select 
    id,username,password,age,sex 
from 
    t_user_info 
where 
    id="10000001' OR '1'='1"(這裏爲方便理解將兩邊的'修改成了",實際爲id='10000001' OR '1'='1',
但是效果爲id="10000001' OR '1'='1")
如果沒有id爲“10000001' OR '1'='1”的信息返回null

非預編譯打印SQL,實際執行SQL

select 
    id,username,password,age,sex 
from 
    t_user_info 
where 
    id='10000001' OR '1'='1'
​
select 
    id,username,password,age,sex 
from 
    t_user_info 
where 
    id='10000001' OR '1'='1'
無論有沒有id爲“10000001',均返回所有用戶信息

總結

預編譯(#{})會將SQL提前編譯好,#{}位置爲佔位符,執行時候一個佔位符就對應一個變量,不會影響到SQL結
構,所以不會存在SQL注入問題;
非預編譯(${})不會提前編譯SQL,${}位置會直接將變量拼接進來,會影響到SQL的本身機構

Mybatis的SQL緩存

Mybatis的預編譯會將編譯後的SQL緩存起來,再次遇到相同的SQL會直接使用不會再次編譯

Mybatis的SQL優化

預編譯階段可以對sql語句進行優化;
預編譯可以將多個操作步驟合併成一個步驟,一般而言,越複雜的sql,編譯程度也會複雜,難度大,耗時,費性
能,而預編譯可以合併這些操作,預編譯之後DBMS可以省去編譯直接運行sql。(節選https://www.jianshu.com
/p/59155963d790)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章