1. 在Mapper映射文件中,能夠經過parameterType指定SQL語句所要輸入參數的類型,類型能夠是java簡單類型(String和七個基本類型以及基本類型的包裝類)、hashmap、pojo的包裝類型。java
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dao.UserMapper"> <select id="findUserById" parameterType="java.lang.String" resultType="entity.User"> select * from cn_user where cn_user_id=#{id} </select> </mapper>
2. 在查詢或其餘SQL語句中,所須要的參數多是多個,而parameterType屬性只能指定一個輸入參數的類型,也就是隻能接受一個對象,因此咱們須要將這些參數封裝到一個包裝類中,這個包裝類必須符合JavaBean規範,有時候須要傳入查詢條件很複雜,可能包括用戶信息、其它信息等,而每個數據庫表都對應這一個Java實體類,除非數據庫表的字段發生變化,通常不修改原實體類,建議使用自定義的包裝類型的pojo,在包裝類型的pojo中將複雜的查詢條件包裝進去,好比程序員
//與數據庫User表對應的實體類,類中的每一個屬性名與user表的字段一致,並且符合javabean規範 public class User implements Serializable{ private String cn_user_id; private String cn_user_name; private String cn_user_password; public String getCn_user_id() { return cn_user_id; } public void setCn_user_id(String cn_user_id) { this.cn_user_id = cn_user_id; } public String getCn_user_name() { return cn_user_name; } public void setCn_user_name(String cn_user_name) { this.cn_user_name = cn_user_name; } public String getCn_user_password() { return cn_user_password; } public void setCn_user_password(String cn_user_password) { this.cn_user_password = cn_user_password; } @Override public String toString() { return "User [cn_user_id=" + cn_user_id + ", cn_user_name=" + cn_user_name + "]"; } }
/** * User應用擴展類,用於應變多種需求而創造的類 * 一般不在源類Uesr上直接進行修改,而是經過繼承來添加一些額外的屬性,該類也必須符合javabean規範 * */ public class UserCustom extends User{ //添加某些屬性 }
//經過該類所須要的幾個參數所在的擴展類的對象做爲屬性組合進來,參數輸入映射就經過該類完成 public class queryUserVo{ private UserCustom user; //或包含其餘屬性 public User getUser() { return user; } public void setUser(UserCustom user) { this.user = user; } @Override public String toString() { // TODO Auto-generated method stub return user.getCn_user_name(); } }
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dao.UserDao"> <!--經過 屬性.屬性.屬性··· 的表達式從傳入的參數包裝對象中取出所須要的參數數據--> <select id="findUserById" parameterType="queryUserVo" resultType="UserCustom"> select * from cn_user where cn_user_id=#{user.cn_user_id} </select> </mapper>
2. resultMapsql
1. 在Mapper映射文件中,能夠經過resultMap進行高級輸出映射。數據庫
2. 若是查詢出來的列名和pojo的屬性名不一致,經過定義一個resultMap對列名和pojo屬性名之間做一個映射關係。首先要定義resultMap,而後使用resultMap做爲statement的輸出映射類型。數組
<!--好比下面的SQL語句中查詢獲得的字段名爲name而不是cn_user_name,與User中的屬性名沒法對應,會產生問題--> <select id="findUserById" parameterType="java.lang.String" resultType="entity.User"> select cn_user_name name from cn_user where cn_user_id=#{id} </select> <!--使用resultMap--> <select id="findUserById" parameterType="java.lang.String" resultMap="username"> select cn_user_name name from cn_user where cn_user_id=#{id} </select> <!-- type指查詢結果集所映射的Java類型,能夠是別名或全限定名 id指該resultMap的惟一標識 --> <resultMap type="entity.User" id="username"> <!-- result標籤指定java類型中的屬性property與查詢到的字段column之間的映射關係 --> <result column="name" property="cn_user_name"/> </resultMap>
3. 關聯查詢,首先搞清一對1、一對多和多對多查詢,User表、NoteBook表和Note表,NoteBook表以User表的主鍵做爲外鍵進行關聯,Note表以NoteBook表的主鍵做爲外鍵進行關聯:mybatis
若是使用resultMap實現一對一關聯查詢,須要單獨定義resultMap,實現有點麻煩,若是對查詢結果有特殊的要求,使用resultMap能夠完成將關聯查詢映射pojo的屬性中。app
resultMap能夠實現延遲加載,resultType沒法實現延遲加載。ide
4. resultMap對於一對一查詢的使用:以User用戶表與NoteBook筆記本表爲例,NoteBook表爲查詢主表,經過NoteBook表中的User表外鍵關聯查詢User表中的數據this
public class NoteBook implements Serializable { private String cn_notebook_id; private String cn_user_id; private String cn_notebook_type_id; private String cn_notebook_name; private String cn_notebook_desc; private Timestamp cn_notebook_createtime; //省略get/set方法 } public class User implements Serializable{ private String cn_user_id; private String cn_user_name; private String cn_user_password; private String cn_user_token; private String cn_user_nick; //省略get/set方法 } //若是隻須要查詢獲得User中的部分屬性,能夠直接寫屬性,而不須要將整個User對象做爲屬性 public class UserAndNoteBook1 extends NoteBook { private String cn_user_name; // private String cn_user_id; public String getCn_user_name() { return cn_user_name; } public void setCn_user_name(String cn_user_name) { this.cn_user_name = cn_user_name; } } public class UserAndNoteBook2 extends NoteBook{ private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dao.NoteBookDao"> <!-- 經過resultType實現一對一映射 將整個查詢的結果映射到entity.UserAndNoteBook1類中 --> <select id="findNoteBookAndUser1" parameterType="String" resultType="entity.UserAndNoteBook1"> select cn_notebook.*,cn_user_name from cn_notebook,cn_user where cn_user.cn_user_id=cn_notebook.cn_user_id and cn_notebook.cn_notebook_id=#{id} </select> <!-- 經過resultMap實現一對一映射 --> <select id="findNoteBookAndUser2" parameterType="String" resultMap="UserAndNoteBook"> select cn_notebook.*,cn_user.* from cn_notebook,cn_user where cn_user.cn_user_id=cn_notebook.cn_user_id and cn_notebook.cn_notebook_id=#{id} </select> <!-- 定義映射結果集resultMap type指定將整個查詢的結果映射到entity.UserAndNoteBook2類中, id爲當前定義的resultMap在整個Mapper文件中惟一標示,經過該id屬性來引用該resultMap --> <resultMap type="entity.UserAndNoteBook2" id="UserAndNoteBook"> <!-- id:指定查詢列中的主鍵,訂單信息的中的主鍵,若是有多個主鍵,配置多個id column:數據庫表中的字段名 property:類中的屬性名 經過column和property將數據庫表中的字段映射到pojo類中指定的屬性中 --> <id column="cn_notebook_id" property="cn_notebook_id"/> <result column="cn_user_id" property="cn_user_id"/> <result column="cn_notebook_type_id" property="cn_notebook_type_id"/> <result column="cn_notebook_name" property="cn_notebook_name"/> <result column="cn_notebook_desc" property="cn_notebook_desc"/> <result column="cn_notebook_createtime" property="cn_notebook_createtime"/> <!-- association:用於映射關聯查詢單個對象的信息,一對一關聯映射查詢實現的關鍵標籤 property:要將關聯查詢的用戶信息映射到UserAndNoteBook2類中的user屬性中 javaType:指定映射的user屬性的類型 --> <association property="user" javaType="entity.User"> <id column="cn_user_id" property="cn_user_id"/> <result column="cn_user_name" property="cn_user_name"/> <result column="cn_user_password" property="cn_user_password"/> <result column="cn_user_token" property="cn_user_token"/> <result column="cn_user_nick" property="cn_user_nick"/> </association> </resultMap> </mapper>
5. resultMap對於一對多查詢的使用:以User用戶表與NoteBook筆記本表爲例,User表爲查詢主表,經過User表中的主鍵關聯查詢NoteBook表中的數據,一行User數據(或者說一個User對象)對應多行NoteBook數據(多個NoteBook對象)spa
public class UserCustom extends User{ private List<NoteBook> books; public List<NoteBook> getBooks() { return books; } public void setBooks(List<NoteBook> books) { this.books = books; } }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dao.UserDao"> <select id="findUserWithNoteBook" parameterType="java.lang.String" resultMap="UserWithNoteBook"> SELECT cn_notebook.*, cn_user.* FROM cn_notebook, cn_user WHERE cn_user.cn_user_id = cn_notebook.cn_user_id and cn_user.cn_user_id=#{id} </select> <resultMap id="UserWithNoteBook" type="entity.UserCustom"> <id column="cn_user_id" property="cn_user_id"/> <result column="cn_user_name" property="cn_user_name"/> <result column="cn_user_password" property="cn_user_password"/> <result column="cn_user_token" property="cn_user_token"/> <!--對於一對多關係映射,應使用collection 子標籤, property指定將全部查詢到的NoteBook集合存放到books屬性對象中, ofType指定查詢到的每一條NoteBook數據都映射爲entity.NoteBook類對象 --> <collection property="books" ofType="entity.NoteBook"> <id column="cn_notebook_id" property="cn_notebook_id"/> <result column="cn_user_id" property="cn_user_id"/> <result column="cn_notebook_type_id" property="cn_notebook_type_id"/> <result column="cn_notebook_name" property="cn_notebook_name"/> <result column="cn_notebook_desc" property="cn_notebook_desc"/> <result column="cn_notebook_createtime" property="cn_notebook_createtime"/> </collection> </resultMap> </mapper>
6. resultMap對於多對多查詢的使用:以User用戶表與NoteBook筆記本表與Note筆記表爲例,User表爲查詢主表,經過User表中的主鍵關聯查詢NoteBook表中的數據,一行User數據(或者說一個User對象)對應多行NoteBook數據(多個NoteBook對象),而後再經過查詢到的每個NoteBook中的主鍵id,關聯查詢該NoteBook有多少Note
public class Note implements Serializable{ private String cn_note_id; private String cn_notebook_id; private String cn_note_title; private String cn_note_body; //省略get/set方法 } public class NoteBookVo extends NoteBook{ private List<Note> notes; public List<Note> getNotes() { return notes; } public void setNotes(List<Note> notes) { this.notes = notes; } } public class UserVo extends User{ private List<NoteBookVo> books; public List<NoteBookVo> getBooks() { return books; } public void setBooks(List<NoteBookVo> books) { this.books = books; } }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dao.UserDao"> <select id="find" parameterType="java.lang.String" resultMap="UserVo"> SELECT cn_notebook.*, cn_user.*,cn_note.* FROM cn_notebook, cn_user, cn_note WHERE cn_user.cn_user_id = cn_notebook.cn_user_id and cn_user.cn_user_id=#{id} and cn_note.cn_notebook_id=cn_notebook.cn_notebook_id </select> <resultMap id="UserVo" type="entity.UserVo"> <id column="cn_user_id" property="cn_user_id"/> <result column="cn_user_name" property="cn_user_name"/> <result column="cn_user_password" property="cn_user_password"/> <result column="cn_user_token" property="cn_user_token"/> <collection property="books" ofType="entity.NoteBookVo"> <id column="cn_notebook_id" property="cn_notebook_id"/> <result column="cn_user_id" property="cn_user_id"/> <result column="cn_notebook_type_id" property="cn_notebook_type_id"/> <result column="cn_notebook_name" property="cn_notebook_name"/> <result column="cn_notebook_desc" property="cn_notebook_desc"/> <result column="cn_notebook_createtime" property="cn_notebook_createtime"/> <collection property="notes" ofType="entity.Note"> <id column="cn_note_id" property="cn_note_id"/> <result column="cn_notebook_id" property="cn_notebook_id"/> <result column="cn_note_title" property="cn_note_title"/> <result column="cn_note_body" property="cn_note_body"/> </collection> </collection> </resultMap> </mapper>
6. 關於resultMap中的關聯查詢映射,實際上主要就是collection與association兩個子標籤的運用,這兩個子標籤之間能夠互相嵌套,以應對要映射的類中包含pojo類型的屬性或者是包含集合類型的屬性,或者是屬性的屬性中包含pojo類型的屬性或包含集合類型的屬性,經過collection與association兩個子標籤的互相嵌套使用就能夠解決具備複雜屬性的映射類問題。若是過屬性爲集合就使用collection,若是爲pojo類型就使用association,二者須要之間的使用區別就在於collection標籤的屬性中指定集合中元素映射的類型使用ofType,association標籤的屬性中指定映射的類型使用javaType。
1. 動態SQL即Mybatis對sql語句進行靈活操做,經過一些標籤進行判斷,對sql進行靈活拼接、組裝。
2. 條件判斷標籤<if test=""></if>:對輸入的參數進行判斷,若是輸入參數知足條件才進行SQL語句拼接。若是傳入的參數是一個包裝對象,那麼就經過屬性.屬性.屬性··來對參數進行判斷
<!--無判斷sql--> <select id="findUserById" parameterType="entity.User" resultType="entity.User"> select * from cn_user where cn_user_id=#{id} and cn_user_name=#{cn_user_name} and cn_user_password=#{cn_user_password} </select> <!--無判斷添加if標籤判斷--> <select id="findUserById" parameterType="entity.User" resultType="entity.User"> select * from cn_user <!-- where標籤至關於sql中的where關鍵字,但該標籤還能夠自動消除拼接的sql語句中第一個and、or關鍵字 好比,若是cn_user_name爲空那麼就會拼接and cn_user_password=#{cn_user_password},and關鍵字是多餘的 而where標籤就會消除and標籤,並且還至關於where關鍵字 --> <where> <!-- 判斷參數是否爲空 --> <if test="cn_user_name!=null and cn_user_name!=''"> and cn_user_name=#{cn_user_name} </if> <if test="cn_user_password!=null and cn_user_password!=''"> and cn_user_password=#{cn_user_password} </if> </where> </select>
3. SQL片斷:將一些的頻繁出現的sql代碼塊提取出來,成爲一個SQL片斷,能夠提升SQL的複用性,其它的statement中就能夠引用sql片斷,方便程序員進行開發,經過標籤<sql id=""></sql>定義,好比將上面的判斷條件部分的提取爲一個代碼塊
<!-- 經過id定義該SQL片斷在當前Mapper文件中的惟一標示,經過該id就能夠被其餘sql語句引用 通常來講SQL片斷要基於單表,其次SQL片斷中不要出現where關鍵字或者where標籤,由於若是sql片斷中 有了一個where那麼組合其餘sql片斷是就會出現錯誤 --> <sql id="query_if"> <!-- 判斷參數是否爲空 --> <if test="cn_user_name!=null and cn_user_name!=''"> cn_user_name=#{cn_user_name} </if> <if test="cn_user_password!=null and cn_user_password!=''"> and cn_user_password=#{cn_user_password} </if> </sql> <select id="findUserById" parameterType="entity.User" resultType="entity.User"> select * from cn_user <where> <!-- 引用sql片斷,若是引用的SQL片斷在另外一個mapper文件中,那麼就要在SQL片斷的id 前面加上SQL片斷所在的mapper文件的namespace,好比 usermapper.query_if --> <include refid="query_if"></include> </where> </select>
4. 若是Mapper映射文件中sql語句的映射輸入對象是一個包裝對象,並且該包裝對象的屬性是一個List或者數組對象,能夠經過foreach 標籤來對該屬性對象進行解析遍歷:好比以下兩種sql語句形式
第一種形式:select * from cn_user where cn_user_id=123 or cn_user_id=2342 or cn_user_id=34636 該形式中的where部分可變爲以下SQL片斷 <where> <!-- collection:指定輸入映射對象中的List或數組類型的屬性 separator:指定遍歷拼接的兩個片斷之間進行分隔 的關鍵字,好比and、or index:用來表示遍歷的每一個元素的下標,能夠經過該index屬性值來提取元素下標 item:用來表示遍歷的每一個元素 open:表示遍歷拼接SQL片斷以前要添加的SQL片斷 close:表示遍歷拼接SQL片斷以後要添加的SQL片斷 --> <foreach collection="ids" separator="or" index="index" item="id" open="(" close=")"> cn_user_id=#{id}<!--注意,這裏的#{}中必須寫與item指定的字符串相同--> </foreach> </where> 第二種形式:select * from cn_user where cn_user_id in (1,2,3,4) 該形式中的where部分可變爲以下SQL片斷 <where> <foreach collection="ids" separator="," index="index" item="id" open="cn_user_id in (" close=")"> #{id}<!--注意,這裏的#{}中必須寫與item指定的字符串相同--> </foreach> </where>
<foreach collection="" separator="" index="" item="" open="" close=""></foreach>