這幾天在公司做專案,到了收尾的階段,但是發現自己在使用mybatis的時候給自己留下了很多的坑,於是乎花了兩天的時間來除錯和重新構思自己寫下的mapper.xml檔案,總算是有些收穫,在這裡分享給大家。

一、何為mapper.xml

        mapper.xml是mybatis中的重要的組成部分,也算是核心之一,我們可以看到的就是他是由一些定義好的查詢資料庫的語句和一些xml規範定義好的。我們在使用mybatis的時候可以看到,在這裡mapper檔案相當於是一個dao層介面的實現,因為mapper中定義的查詢,id都必須要和dao層的方法是一致的,這樣才可以進行查詢。這裡最能體現mybatis特點的就是這個mapper配置檔案了,因為mybatis能從裡面的內容讀取對映,生成sql語句進行查詢。

二、mapper的寫法和注意事項

        我們的mapper有很多種使用方法,這裡簡要說明與總結一下:

(1)、直接當做sql語句使用

        我們可以使用mapper中的<select><udpate><insert><delete>標籤來拼接我們的sql語句,這裡寫的標籤為mybatis解析的頭,所以我們對應的sql語句必須寫在對應的標籤下面,方可成功。

(2)、加判斷的條件查詢語句

         在mapper中,我們可以對條件加上應有的判斷,來進行一些分條件的查詢,尤其是在where子句中,這裡注意的是,使用判斷,也就是if也是一個標籤為<if test=""></if> 其中在test中為if的判斷條件,這裡的判斷就是一些取值的判斷,並沒有其他的作用但是寫法需要注意,可以直接使用Dao介面中傳下來的變數直接進行判斷。如下語句為增加了一個判斷用於拼接sql語句用的:

<if test='state=="0"'>
   AND t_acceptanceform.acceptancestate!='0'
</if>
<if test='state!=0'>
   AND t_acceptanceform.acceptancestate =#{state}
</if>
        這裡就是在where中通過變數不同的條件來選擇不同的語句,使sql語句更加的靈活。

(3)、增加一些變數集合,用於查詢或者返回值
         這裡所指的變數集合其實是兩種,一種是map型別的集合,一種是sql中自定義查詢欄位集合,我們在做返回值還有mybatis自動生成的程式碼中常見的就是這種map集合,一般叫做resultmap,他是可以和pojo等型別的實體類進行對應的,用於對於查詢返回值的接收和傳送,可以被mybatis機制自動轉換為一些List集合或者其他的集合之類的東西。

格式:

<resultMap id="" type="" >     <!--id為標識這個map的唯一標誌,不能重複,type為對應到的pojo包路徑-->
    <id column="" property="" jdbcType="" />    <!--column是列名,property為對應projo物件名,type就是資料庫中的型別-->
    <result column="" property="" jdbcType="" />
</resultMap>

第二個是<sql>標籤為頭的一般查詢結果集,他的好處是可以自定義,也可以加入一些判斷,我們在做複雜查詢的時候一般可以用到他,下面是我寫的一個例子:

<sql id="outPutOrderDetail">
		outputrepositorycode,
		outdate,
		consignee,
		ordersno,
		repocode,
		transferpath,
		acceptanceformcode,
		address,
		totalproducts,
		createtime,
		batchcount,
		comments,
		customerid,
        pitposition
</sql>

使用的查詢:
<select id="queryOutPutHead" resultType="com.cn.echuxianshengshop.pojo.ext.OutPutOrderDetail">
	SELECT
	 <include refid="outPutOrderDetail"/>
	FROM
	t_outputorderb , t_acceptanceform ,t_orders
	WHERE
	  ordercode=belongorderid AND ordercode=ordersNo AND outputrepositorycode=#{opCode}
</select>

        這裡再附上軟體自動生成的<sql>標籤內容,沒有仔細研究過裡面的東西,但是用到了for迴圈和if,應該就是邏輯判斷的一種,和寫條件都是差不多的。
<sql id="Example_Where_Clause" >
    <where >
      <foreach collection="oredCriteria" item="criteria" separator="or" >
        <if test="criteria.valid" >
          <trim prefix="(" suffix=")" prefixOverrides="and" >
            <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 collection="criterion.value" item="listItem" open="(" close=")" separator="," >
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>

這裡就是mybatis裡面用於拼接查詢條件進行查詢的一個拼接判斷,可以好好研究一下。

三、傳值的注意

        我們都知道,在mapper中寫查詢的時候,我們都會用到一些查詢條件和傳入變數進行關聯的事情,一般這種都用的是#{變數名}或者是${變數名}來做取值,那麼他們到底有什麼區別呢?

        1、#{param}會產生PreparedStatement,並且可以安全地設定引數(=?)的值。以為sql語句已經預編譯好了,傳入引數的時候,不會重新生產sql語句。安全性高。
        2、${parem}則直接將{}號中的param插入字串,會產生sql注入的問題:
例如:select * from userwhere userName= ${userName} 
輸出的結果為
select * from userwhere userName= “小明”
        3、在特定場景下,例如如果在使用諸如order by '{param}',這時候就可以使用${}
        4、#{}方式能夠很大程度防止sql注入,${}方式無法防止sql注入
        5、${}方式一般用於傳入資料庫物件,例如傳入表名

字串替換:

        預設情況下,使用#{}格式的語法會導致MyBatis建立預處理語句屬性並以它為背景設定安全的值(比如?)。這樣做很安全,很迅速也是首選做法,有時你只是想直接在SQL語句中插入一個不改變的字串。比如,像ORDER BY,你可以這樣來使用:
       ORDER BY ${columnName}
       這裡MyBatis不會修改或轉義字串。
       重要:接受從使用者輸出的內容並提供給語句中不變的字串,這樣做是不安全的。這會導致潛在的SQL注入攻擊,因此你不應該允許使用者輸入這些欄位,或者通常自行轉義並檢查。

      這裡一定要注意的是,可以用#{param}的時候儘量不要用${param}。