mybatis知識點分析之sql映射語句

sql映射文件

mybatis最強大的低於就在於sql映射語句,mybatis專注於sql,對於開發人員來說,可以最大限度地調優,保證性能。

1.Mapper:映射文件的根節點,只有一個屬性namespace(命名空間)

      作用:(1)用於區分不同的mapper,全局唯一。

                 (2)綁定Dao接口,即面向接口編程,當綁定一個接口,就不需要編寫該接口的實現類,會通過接口的完全限
                          定名找到對應的 mapper配置來執行sql語句,所以namspqce必須要先接口的完全限定名。

2.cache:配置給定命名空間的緩存。

3.cache-ref:從其他命名空間引用緩存配置。

4.resultMap:用來描述數據庫結果集和對象的對應關係。

5.sql:可以重用的sql快,可以被其他語句使用。

6..insert:映射插入語句。

7.update:更新映射語句。

8.delete:刪除映射語句。

9.select:映射查詢語句。

使用select完成單條件查詢

<!--傳入實體類參數時最好不要寫parameterType=“實體類路徑”,更不要寫mybatis不用的parameterMap,會報錯的。不寫的話只要mapper接口中傳入此類,mybatis會自動處理傳參,可以直接使用裏面的屬性值。-->
<select id = "getUser" resultType = "User" parameterType = "string">
  select * from user where name like concat('%',#{name},'%')    //按照姓名模糊查詢。
</select>

       id爲GetUserByName的映射語句,參數類型爲String,返回類型爲User。

      1.#{參數名}:告訴MyBatis生成的PreparedStatement參數,相對於JDBC,該參數被標識爲‘?’。

      2.id:命名空間的唯一標識符,可以被用來引用這條語句。

      3.parameterType:查詢語句傳入的參數類型和完全限定名或者別名,支持基礎數據類型和複雜數據類型,上述傳入的

        參數是個別名,代表Sting。

別名與java類型映射
別名 映射類型 別名 映射類型
string   String double Double
byte Byte float Float
long  Long boolean Boolean
short Short date Date
int Integer map Map
integer Integer hashmap HashMap
arraylist ArrayList list List

4.resultType:查詢語句結果返回類型完全限定名或者別名。別名使用方式跟parameterType一樣。

 

使用select完成多條件查詢

      使用複雜數據類型,把條件參數封裝爲對象、Map進行入參。不管什麼類型的參數,或者多少個參數,都可以封裝爲

      一個Map進行入參,通過map的key或者傳入的參值。

<select id="getUser" resultType="User" parameterType="map">
     select * from user where userName like CONCAT('%',#{name},'%')  and age= #{age}
</select>

 

使用resultMap完成查詢結果的展現

    resultMap:做自定義映射,實體類屬性名和數據庫列名不一致的情況下,並且可以指定要顯示的列,使用靈活,應用廣

    泛。

    實體類  User.xml

package com.mybatis.usermanage.entity;

public class User {
    private Integer id;
    private String name;
    private Integer age;
    //一對一查詢使用
    private School school;
    //一對多查詢使用
    private set<Furniture> furnitureSet = new HashSet<Furniture>();
    
	public User() {
		super();
	}
	
	public User(Integer id,String name, Integer age,School school) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.school=school;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}

	public School getSchool() {
		return school;
	}

	public void setSchool(School school) {
		this.school = school;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age
				+ ", school=" + school.toString() + "]";
	}
    

}

    映射配置

<!--resultMap標籤的作用是,當實體類中的屬性與數據庫中的表字段不一致時可以通過該標籤來進行映射 --><!--id自定義,在select的resultMap屬性中使用,type表示map中的value類型 -->
<resultMap id="userMaps" type="com.mybatis.usermanage.entity.User">
    <id column="id" property="id"/>
    
    <!-- 使用result來映射需要映射的字段,column表示表字段,property表示實體類屬性 -->
    <result column="userName" property="Name"/>
 </resultMap>
 
<id表示接口方法,resultMap上面resultMap標籤的id>
<select id="userMap"  resultMap="userMaps">
    select *  from user 
</select>

      屬性和子節點:

   id:唯一標識,此id值用於select元素resultMap屬性的引用。

     type:標識該resultMap的映射結果類型。

     result子節點:標識一些簡單屬性,其中column屬性代表數據庫的字段名,property代表查詢出來的字段名映射到

                               pojo類的某個屬性。   

     id子節點:與result子節點作用一樣,一般表示數據庫的主鍵列。

      resultType和resultMap的對比如下 :

          1.resultType:直接表示返回類型, 包括基本數據類型和複雜數據類型。

          2.resultMap:外部resultMap定義的引用,通過對應的外部resultMap的id,表示結果映射到哪個resultMap上,一

                              般用於字段名和屬性名不一致的情況,或者需要做複雜的聯合查詢以便自由控制映射結果。

          3.兩者的關聯
             當進行查詢時,查詢出來的每個字段都會放在一個Map裏,當查詢元素返回屬性是resultType的時候,會將鍵值

             對取出賦所指定的屬性。其實MyBatis的每個查詢映射的返回類型都是resultMap,只是當我們使用resultType的

             時候,會自動把對應的值賦給所指定的對象屬性,當使用resultMap時候,因爲map不是很好的表示領域,我們就

             進一步的轉化爲對應的實體對象。resultMap主要作用於複雜的聯合查詢上。

            注意:resultType和resultMap本質上是一樣的,都是Map數據結構,但是二者不能同時存在。

          4.resultMap的自動映射級別:默認級別爲partial,也可以在settings更改值。     

      <settings>
           <!-- 設置resultMap的自動映射級別爲NONE(禁止自動匹配) -->
           <setting name = "autoMappingBehavior" value = "NONE">
     </settings>

使用MyBatis實現增刪改操作

     1.使用insert完成增加操作

 <insert id="add" parameterType="User">   

      INSERT INTO user(name,age) VALUES(#{name},#{age})
</insert>

    2.使用update完成修改操作

   <update id="update" parameterType="User">
      UPDATE user SET name= #{name},age= #{age} WHERE id = #{id}
   </update>

 3.使用delete完成刪除操作

   <delete id="User" parameterType="integer">
       delete from user where id = #{id}
   </delete>

      元素中的屬性:

   id:與select元素id一樣,命名空間的唯一標識符。

   parameterType:傳入參數的類型的完全限定名或者別名。

     對於增刪改操作的注意事項:

     (1)該類型的操作本身默認返回執行SQL影響的行數,所以DAO層的接口方法返回值一般爲int類型,最好不要

          boolean類型。

     (2)insert、update、delete元素中均沒有resultType屬性,只有查詢操作需要對返回結果類型(resultType/resultMap)

         進行相應的指定。

使用resultMap實現高級結果映射

   1.assocation:

      映射到javaBean的某個複雜的“數據類型”屬性,僅處理一對一的關聯關係。(school中的信息與user中是一對一關

      系)

      實體類  School.java  User.java見上

package com.mybatis.usermanage.entity;

public class School {
	private Integer id;
	private String schoolName;
	private String profession;
	private String className;
	private Integer userId;
	public School() {
		super();
	}
	
	public School(Integer id, String schoolName, String profession,
			String className,Integer userId) {
		super();
		this.id = id;
		this.schoolName = schoolName;
		this.profession = profession;
		this.className = className;
		this.userId = userId;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getSchoolName() {
		return schoolName;
	}
	public void setSchoolName(String schoolName) {
		this.schoolName = schoolName;
	}
	public String getProfession() {
		return profession;
	}
	public void setProfession(String profession) {
		this.profession = profession;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	
	public Integer getUserId() {
		return userId;
	}

	public void setUserId(Integer userId) {
		this.userId = userId;
	}

	@Override
	public String toString() {
		return "School [id=" + id + ", schoolName=" + schoolName
				+ ", profession=" + profession + ", className=" + className
				+", userId=" + userId + "]";
	}
	
}

  

<!--一對一聯合查詢-->
<resultMap id="schoolMaps" type="com.mybatis.usermanage.entity.User">
     <id property="id"  column="id"/>
     <result property="name" column="name"/>
        
     <association標籤用於映射查詢副表數據,property對應主實體類中的的屬性名,javaType對應該
      副實體類全稱類名>
     <association property="school" javaType="com.mybatis.usermanage.entity.School">
        <id property="id" column="id"/>
        <result property="profession" column="profession"/>
        <result property="schoolName" column="school_name"/>
        <result property="className" column="class_name"/>
        <result property="userId" column="user_id"/>   
     </association>
</resultMap>

<id表示接口方法,resultMap上面resultMap標籤的id>
<select id="schoolMap" resultMap="schoolMaps">
    select *  from user u,school s where u.id=s.user_id and u.name=#{name}
</select>

        

 

  association的屬性節點:

    property:映射數據庫列的實體對象屬性名。

    javaType:完整的java類名和限定名。

              property: 所映射的屬性的類型。

    子元素:id:一般爲映射主鍵,可以提高性能。

        result:

          column:映射的數據庫的字段名。

          property:映射的數據列對應的實體對象屬性。

    2.collection:

       映射到JavaBean的某個複雜的“數據類型”的屬性,這個屬性是一個集合列表,處理一對多的關聯關係。

<resultMap id="furnitureMaps" type="com.mybatis.usermanage.entity.User">
     <id property="id"  column="id"/>
     <result property="name" column="name"/>
     <result property="age" column="age"/>
    
     <collection property="furnitureSet" ofType="com.mybatis.usermanage.entity.Furniture">
     <!-- 如果兩表聯查,主表和明細表的主鍵都是id的話,明細表的多條只能查詢出來第一條,因此要將 
     furniture表的主鍵字段名Id另取名-->
          <id property="id" column="furniture_id"/>
          <result property="userId" column="user_id"/>  
          <result property="furnitureName" column="furniture_name"/>          
      </collection>
</resultMap>
    
<select id="furnitureMap" resultMap="furnitureMaps">
     select *  from user u,furniture f where u.id=f.user_id and u.name=#{name}
</select>

  ofType:完整的java類名和限定名。

  property:所映射的屬性的類型。

  其餘和association基本一致。

 

MyBatis緩存

1.一級緩存:基於PerpetualCache(MyBatis自帶)的HashMap本地緩存。作用域在Session域內,當session flush或者

   close之後,該緩存被清空。

2.二級緩存:global Cache,超出session範圍之外,可以被所有SqlSession共享。開啓它只需在MyBatis的核心配置文件

   settings 設置即可。

  補充:一級緩存緩存的是SQL語句,二級緩存緩存的是結果對象。

3.二級緩存配置:

  (1)開啓二級緩存;

<settings>
        <setting name="cacheEnabled" value = "true"/>
<settings>

  (2)mapper文件中設置緩存,默認是沒有開啓緩存的。作用域是針對namespace而言的,只在namespace內的查

           詢才能共享這個cache。

  (3)對個別查詢進行緩存,單獨設置cache:

<select id = "getUser" resultType = "User" useCache = "true">
    ...........
</select>

        補充:對MyBatis的緩存瞭解就可以了,對結果集做緩存並不是MyBatis所擅長的,而且性能也不是很好,它專心

                做的應該是SQL映射。

動態SQL

一、使用動態SQL完成多條件查詢。

動態SQL基於OGNL的表達式,我們可以方便的在SQL語句中實現某些邏輯,用於實現動態SQL元素如下:

  if:利用if實現簡單的條件選擇。

  choose(when,otherwise):相當於java中的switch語句,通常與when和otherwise搭配。

  set:解決動態更新語句。

  trim:靈活的去除多餘的關鍵字。

  foreach:迭代一個集合,通常用於in條件。

二、if+where實現多條件查詢

複製代碼

<select id="getUser" parameterType="Map" resultType="user">
    select * from user
    <where>
       <if test="age!= null and age!= 0">
          name = #{age}
       </if>
       <if test="name != null and name != ''">
           and name like CONCAT('%',#{name},'%')
       </if>
    </where>
</select>

複製代碼

where元素可以智能的處理and 和 or 的多餘問題, 不需擔心多餘關鍵字導致語法錯誤。

if元素的test用於判斷表達式是否符合,符合則繼續拼接SQL語句。

三、if+trim+foreach實現多條件查詢

複製代碼

<select id="getUser" resultType="user">
       select * from user

       <trim prefix="where" prefixOverrides="and | or">
             <if test="id!=null">
                 id in
                 <foreach collection="userIds" item="ids" open="(" close=")" separator=",">
                     #{ids}
                 </foreach>
            </if>
            <if test="age!= null and age!= 0">
                 and age= #{age}
             </if>
      </trim>
</select>

複製代碼

(1)trim的屬性:

  prefix:前綴: 作用是通過自動識別是否有返回值後,在trim包含的內容上加上前綴,如上述示例的where。

  suffix:後綴: 作用是在trim包含的內容上加上後綴。

  prefixOverrides: 對於trim包含內容的首部進行指定內容,(如上述示例的 and | or) 的忽略(去餘);

  suffixOverrides: 對於trim包含內容的首位部進行指定內容的忽略。

(2)foreach的屬性:

  item:表示集合中每一個元素進行迭代時的別名。

  index: 指定一個名稱,表示在迭代的過程中,每次迭代到的位置。

  open:表示該語句以什麼開始(既然是in條件語句,必然是 ' ( ' 開始)

  separator: 表示每次進行迭代的時候以什麼符號作爲分隔符(既然是in條件語句,必然是 ' , ' 分隔)

  close: 表示該語句以什麼結束(既然是in條件語句,必然是 ' ) ' 結束)

  collection:最關鍵,並且最容易出錯的屬性。需注意,該屬性必須指定,不同情況下,該屬性值是不同的,主要有

              三種情況:

    若傳入的參數是單參數且類型爲一個List的時候,屬性值爲list;

    若傳入的參數是單參數且類型爲一個數組的時候,屬性值爲array;

    若傳入的參數爲多參數時,就需要封裝爲一個map集合進行處理。屬性值爲Map的key;

 

使用set更新操作,類似於上述示例使用方法:

<update id="UpdateUser" parameterType="user">
         update user
         <trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
             <if test="name != null and name != ''">
                 name = #{name},
             </if>
             <if test="age!= null and age!= 0">
                 age= #{age}
             </if>
         </trim>
</update>

三、choose(when、otherwise)

<select id="getUser" resultType="user">
        select * from user where 1 = 1
        <choose>
            <when test="name!= null and name!= ''">
                and name like CONCAT('%',#{name},'%')
            </when>
            <when test="age!= null and proContact != 0">
                and age=#{age}
            </when>
            <otherwise>
                and id = 2016
            </otherwise>
        </choose>
</select>

      when元素:當test屬性中的條件滿足時,就會輸出when元素中的內容,並且當when中一旦有條件滿足時,就會跳

                         出choose,所以只有一個條件會被輸出。

  otherwise元素:當when中的所有條件都不滿足時,則會輸出此元素的內容。

四、MyBatis實現分頁功能

  1.使用聚合函數獲得總記錄數-

  2.實現分頁通過limit(起始位置,頁面顯示量)

補充:起始位置的下標  = (當前頁碼 - 1 ) * 頁面顯示量

<!-- 多條件篩選分頁 -->
    <select id="UserPage" parameterType="map" resultType="user">
        select * from user
        <trim prefix="where" prefixOverrides="and | or">
            <if test="name != null and name!= ''">
                name like concat('%',#{name},'%')
            </if>
            <if test="age!= null and age!= 0">
                and age= #{age}
            </if>
        </trim>
        limit #{startRow},#{pageSize}
    </select>

 

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