1. 程式人生 > >Mybatis-Generator生成Mapper檔案中的問題解答

Mybatis-Generator生成Mapper檔案中的問題解答

寫在前面

由於開源了專案的緣故,很多使用了My Blog專案的朋友遇到問題也都會聯絡我去解決,有的是把問題留在專案的issue裡提出,有的是在我的私人部落格裡留言,還有的則是直接新增我的qq來找我講自己遇到的問題,有些問題比較簡單直接就解決了,有些問題的解決記錄也留在issue記錄裡,有些則是網上有相關教程,而剩下問題的解決方案,如果時間允許我都會單獨的做一篇部落格來解答。

問題描述

當時的聊天記錄:
question

截圖中提到的程式碼(節選):

ContentVoMapper.xml:

 <sql id="Example_Where_Clause">
    <where
>
<foreach collection="oredCriteria" item="criteria" separator="or"> <if test="criteria.valid"> <trim prefix="(" prefixOverrides="and" suffix=")"> <foreach collection="criteria.criteria" item="criterion"> <choose> <when
test="criterion.noValue">
and ${criterion.condition} </when> <when test="criterion.singleValue"> and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue"
>
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue"> and ${criterion.condition} <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql>
CommentVoExample:

    protected abstract static class GeneratedCriteria {
        protected List<Criterion> criteria;

        protected GeneratedCriteria() {
            super();
            criteria = new ArrayList<Criterion>();
        }

        public boolean isValid() {
            return criteria.size() > 0;
        }

        public List<Criterion> getAllCriteria() {
            return criteria;
        }

        public List<Criterion> getCriteria() {
            return criteria;
        }
        ...

問題整理:在GeneratedCriteria類中並沒有valid這一屬性,僅僅只有一個isValid()方法,但是在Mapper檔案中mybatis的<if test>語法中,卻有criteria.valid的表示式,而且程式可以正常執行,這是怎麼回事呢?

思路整理

首先,我剛看到這個問題的時候也是有點懵,因為這個程式碼其實不是我寫的,Mapper檔案是我通過Mybatis-Generator自動生成的,所以這段程式碼我也是有點陌生的,哈哈哈哈。

但是看了一遍程式碼之後,我覺得應該是mybatis根據valid屬性自動找到了isValid()方法,然後執行了邏輯判斷,當然,這都是個人感覺,沒什麼依據,隱隱約約覺得應該是這麼個道理。但是呢,畢竟這位朋友是來問問題的,我不能就簡簡單單的回覆這麼一句話,而且是連我自己都不確定的答案。

jingxi

疑惑的問題有:

  • 並不知道mybatis是不是這個執行流程;
  • 即使是如上的流程,那麼為什麼根本沒有的屬性會被mybatis正常解析;
  • 為什麼mybatis會去執行isValid()方法而不去執行其他的方法。

解決過程

帶著以上的問題和心中的不確定,我唯一能做的就是去檢視這部分過程的原始碼了,最終也如願得到了答案,通過IDEA的debug功能得到了程式碼的執行過程,可以自行執行檢視一下整個過程:

  • IfSqlNode類中,獲取了if test標籤中表達式的值:criteria.valid;

IfSqlNode

  • 接著是在ObjectPropertyAccessor類中解析到了需要操作的屬性值Criteria類中的valid;

ObjectPropertyAccessor

  • 然後是在OgnlRuntime類中得到了表示式對應執行的MethodisValid()方法。

OgnlRuntime

接下來就是執行方法並獲取返回值了,就不再截圖了。

上面的前兩個問題就有了答案:

  • <if test="criteria.valid">到執行isValid()方法的執行流程找到了,雖然過程較多但是幾個重要的節點就是以上三點,獲取Mapper表示式中的類名和屬性值,然後獲取需要執行的方法,最終實現整個功能。
  • mybatis並沒有去關注是否存在這個屬性,而是根據屬性去找到對應的方法並執行。

至於第三個問題,我也做了一下擴充套件,如果其他帶有valid字串的方法會不會也被執行到,結果是肯定回答,如圖:

isValid()改為getValid()

getValid

OgnlRuntime類中得到了對應執行的MethodgetValid()方法

OgnlRuntime-get

當兩個方法都存在時,會執行isValid()方法,因為if test需要的是一個boolean返回值,當只存在getValid()方法時,則會執行getValid()

結語

首發於我的個人部落格

如果有問題或者有一些好的創意,歡迎給我留言,也感謝向我指出專案中存在問題的朋友,關於這篇文章,特別感謝一下@libinghui