Mybatis實戰2:標簽詳解

image.png

一、select標簽

1.標簽屬性

  • id 唯一的名稱,對應dao中mapper的接口名稱
  • paramterType 定義傳入的參數類型
  • resultType 返回數據類型對應實體類
  • resultMap 外部 resultMap 的命名引用。結果集的映射是 MyBatis 最強大的特性,對其有一個很好的理解的話,許多復雜映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同時使用
  • flushCache 將其設置為 true,任何時候只要語句被調用,都會導致本地緩存和二級緩存都會被清空,默認值:false
  • useCache 將其設置為 true,將會導致本條語句的結果被二級緩存,默認值:true
  • timeout 這個設置是在拋出異常之前,驅動程序等待數據庫返回請求結果的秒數。默認值為 unset(依賴驅動),若設置10,則表示10秒內數據庫沒有返回結果就拋出異常
  • fetchSize 這是嘗試影響驅動程序每次批量返回的結果行數和這個設置值相等。默認值為 unset(依賴驅動),比如設置為20,而你要查詢的總記錄是100條,驅動會每次批量查詢20條,共查詢5次,myabtis會將這5次結果聚合一起返回100條。注意Mysql是不支持fetchSize的
  • statementType STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認值:PREPARED
  • resultSetType FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一個,默認值為 unset (依賴驅動)
  • databaseId 如果配置了 databaseIdProvider,MyBatis 會加載所有的不帶 databaseId 或匹配當前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。
  • resultOrdered 這個設置僅針對嵌套結果 select 語句適用:如果為true,就是假設包含了嵌套結果集或是分組了,這樣的話當返回一個主結果行的時候,就不會發生有對前面結果集的引用的情況。這就使得在獲取嵌套的結果集的時候不至導致內存不夠用。默認值:false。
  • resultSets 這個設置僅對多結果集的情況適用,它將列出語句執行后返回的結果集并每個結果集給一個名稱,名稱是逗號分隔的。

2.查詢示例

1.簡單查詢

mapper接口

    // 根據 id 獲得數據庫中的 username 字段的值
    String getUserNameById(Integer id);

mapper.xml

<!-- 
        指定 resultType 返回值類型時 String 類型的,
        string 在這里是一個別名,代表的是 java.lang.String 

        對于引用數據類型,都是將大寫字母轉小寫,比如 HashMap 對應的別名是 'hashmap'
        基本數據類型考慮到重復的問題,會在其前面加上 '_',比如 byte 對應的別名是 '_byte'
    -->
    <select id="getUserNameById" resultType="java.lang.String">
    select user_name from user_info where id = #{id}
  </select>
2.查詢返回JavaBean

返回Java實體類可以使用resultType屬性
多個查詢條件,可以使用@Param 來指定
mapper接口

// 多個查詢條件,可以使用
UserInfo selectByNamePwd(@Param("userName") String userName, @Param("password") String password);
  <!--通過用戶名和密碼查詢-->
  <select id="selectByNamePwd" resultType="com.gqlofe.userinfo.bean.entity.UserInfo">
    select
    <include refid="Base_Column_List" />
    from user_info
    where user_name = #{userName} and password = #{password}
  </select>
3.返回list類型

mapper方法返回類型是List,則查詢的結果就是List,xml中resultType指定的是返回List的元素的類型

List<UserInfo> selectAll();
  <select id="selectAll" resultType="com.gqlofe.userinfo.bean.entity.UserInfo">
    select * from user_info
  </select>
4.返回Map類型
  • 如果查詢的結果是一條,我們可以把查詢的數據以{表字段名, 對應的值}方式存入到Map中
    MyBatis 還支持將查詢的數據封裝成 Map。其中key是數據庫表字段名,即是下劃線格式
    //  根據 id 查詢信息,并把結果信息封裝成 Map
    Map<String, Object> getMapById(Integer id);
  <select id="getMapById" resultType="hashmap">
    select * from user_info where id = #{id}
  </select>
  • 如果查詢的結果是多條數據,我們也可以把查詢的數據以{表中某一字段名, JavaBean}方式來封裝成Map
    @MapKey 中的值表示用數據庫中的哪個字段名作 key
    @MapKey("id")
    Map<Integer, UserInfo> getAllUserInfoAsMap();
  <!--本可以使用resultType="com.gqlofe.userinfo.bean.entity.UserInfo"-->
  <!--但由于數據庫字段名和實體類屬性名不一致,所以使用resultMap,表示map的value的類型-->
  <select id="getAllUserInfoAsMap" resultMap="BaseResultMap">
    select * from user_info
  </select>

二、insert,update,delete標簽

屬性名稱 釋義 示例
id 唯一的名稱,對應dao中mapper的接口名稱 selectById
paramterType 定義傳入的參數類型 long
flushCache 將其設置為 true,任何時候只要語句被調用,都會導致本地緩存和二級緩存都會被清空,默認值:false fasle
timeout 這個設置是在拋出異常之前,驅動程序等待數據庫返回請求結果的秒數。默認值為 unset(依賴驅動),若設置10,則表示10秒內數據庫沒有返回結果就拋出異常 10
statementType STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認值:PREPARED PREPARED
useGeneratedKeys (僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由數據庫內部生成的主鍵(比如:像 MySQL 和 SQL Server這樣的關系數據庫管理系統的自動遞增字段, oracle使用序列是不支持的,通過selectKey可以返回主鍵),默認值:false。 true
keyProperty (僅對 insert 和 update 有用)唯一標記一個屬性,MyBatis 會通過 getGeneratedKeys 的返回值或者通過 insert 語句的 selectKey子元素設置它的鍵值,默認:unset。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 id
keyColumn (僅對 insert 和 update 有用)通過生成的鍵值設置表中的列名,這個設置僅在某些數據庫(像PostgreSQL)是必須的,當主鍵列不是表中的第一列的時候需要設置。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 id
databaseId 如果配置了 databaseIdProvider,MyBatis 會加載所有的不帶 databaseId 或匹配當前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。

三、sql標簽

定義一些常用的sql語句片段

<sql id="selectParam">
    id, username, password, sex, birthday, address
</sql>

四、include 標簽

引用其他的常量,通常和sql一起使用

<select>
    select <include refid="selectParam"></include>
    from user_info
</select>

五、if 標簽

基本都是用來判斷值是否為空,注意Integer的判斷,mybatis會默認把0變成 ‘’

<if test="item != null and item != ''"></if>

<!-- 如果是Integer類型的需要把and后面去掉或是加上or-->
<if test="item != null"></if>
<if test="item != null and item != '' or item == 0"></if>

六、別名typeAliases標簽

經常使用的類型可以定義別名,方便使用,mybatis也注冊了很多別名方便我們使用,詳情見底部

<typeAliases>
     <typeAlias type="com.gqlofe.userinfo.bean.entity.UserInfo" alias="User"/>
</typeAliases>

七、where標簽

當使用if標簽進行條件判斷時有可能第一個條件不滿足,會導致where語句中多一個and 或者or,如下:

  <select id="selectByNamePwd" resultType="com.gqlofe.userinfo.bean.entity.UserInfo">
    select
    <include refid="Base_Column_List" />
    from user_info
    where
    <if test="userName != null">
      user_name = #{userName}
    </if>
    <if test="password != null">
      and password = #{password}
    </if>
  </select>

如果userName= null,則sql語句就變成

select * from user_info where and password = #{password}

顯然有問題,where標簽可以去除where語句中的第一個and 或 or。
用法:

  <select id="selectByNamePwd" resultType="com.gqlofe.userinfo.bean.entity.UserInfo">
    select
    <include refid="Base_Column_List" />
    from user_info
    <where>
      <if test="userName != null">
        user_name = #{userName}
      </if>
      <if test="password != null">
        and password = #{password}
      </if>
    </where>
  </select>

八、set標簽

update語句中,set標簽可以去除多余的逗號,用法:

<update id="updateByPrimaryKeySelective" parameterType="com.gqlofe.userinfo.bean.entity.UserInfo">
    update user_info
    <set>
      <if test="userName != null">
        user_name = #{userName,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        password = #{password,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        phone = #{phone,jdbcType=VARCHAR},
      </if>
      <if test="icon != null">
        icon = #{icon,jdbcType=VARCHAR},
      </if>
      <if test="sex != null">
        sex = #{sex,jdbcType=INTEGER},
      </if>
      <if test="age != null">
        age = #{age,jdbcType=INTEGER},
      </if>
      <if test="birthday != null">
        birthday = #{birthday,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=BIGINT},
      </if>
      <if test="updateTime != null">
        update_time = #{updateTime,jdbcType=BIGINT},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>

九、trim標簽

where標簽只能去除第一個and或or,不夠靈活,trim標簽功能更加強大。
trim標簽的屬性如下:

  • prefix 在trim標簽內容前面加上前綴
  • suffix 在trim標簽內容后面加上后綴
  • prefixOverrides 移除前綴內容。即 屬性會忽略通過管道分隔的文本序列,多個忽略序列用 “|” 隔開。它帶來的結果就是所有在 prefixOverrides 屬性中指定的內容將被移除。
  • suffixOverrides 移除前綴內容。
<insert id="insertSelective" parameterType="UserInfo" useGeneratedKeys="true" keyProperty="id">
    insert into user_info
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="userName != null">
        user_name,
      </if>
      <if test="password != null">
        password,
      </if>
      <if test="phone != null">
        phone,
      </if>
      <if test="icon != null">
        icon,
      </if>
      <if test="sex != null">
        sex,
      </if>
      <if test="age != null">
        age,
      </if>
      <if test="birthday != null">
        birthday,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="updateTime != null">
        update_time,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="userName != null">
        #{userName,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        #{password,jdbcType=VARCHAR},
      </if>
      <if test="phone != null">
        #{phone,jdbcType=VARCHAR},
      </if>
      <if test="icon != null">
        #{icon,jdbcType=VARCHAR},
      </if>
      <if test="sex != null">
        #{sex,jdbcType=INTEGER},
      </if>
      <if test="age != null">
        #{age,jdbcType=INTEGER},
      </if>
      <if test="birthday != null">
        #{birthday,jdbcType=BIGINT},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=BIGINT},
      </if>
      <if test="updateTime != null">
        #{updateTime,jdbcType=BIGINT},
      </if>
    </trim>
  </insert>

十、foreach標簽

foreach元素的屬性主要有item,index,collection,open,separator,close.

  • collection 要做foreach的對象,作為入參時,List對象默認用"list"代替作為鍵,數組對象有"array"代替作為鍵,Map對象沒有默認的鍵。當然在作為入參時可以使用@Param("keyName")來設置鍵,設置keyName后,list,array將會失效。 除了入參這種情況外,還有一種作為參數對象的某個字段的時候。舉個例子:如果User有屬性List ids。入參是User對象,那么這個collection = "ids".如果User有屬性Ids ids;其中Ids是個對象,Ids有個屬性List id;入參是User對象,那么collection = "ids.id",必填
  • item 合中元素迭代時的別名,必選
  • index 在list和數組中,index是元素的序號,在map中,index是元素的key,可選
  • open foreach代碼的開始符號,一般是(和close=")"合用。常用在in(),values()時。可選
  • separator 元素之間的分隔符,例如在in()的時候,separator=","會自動在元素中間用“,“隔開,避免手動輸入逗號導致sql錯誤,如in(1,2,)這樣,可選。
  • close foreach代碼的關閉符號,一般是)和open="("合用。常用在in(),values()時。可選
<select id="countByUserList" resultType="_int" parameterType="list">
select count(*) from user_info
  <where>
    id in
    <foreach item="item" collection="list" separator="," open="(" close=")" index="">
      #{item.id, jdbcType=NUMERIC}
    </foreach>
  </where>
</select>

<select id="dynamicForeach2Test" resultType="Blog">
     select * from t_blog where id in
     <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
          #{item}
     </foreach>
</select>

十一、choose,when,otherwise標簽

功能有點類似于Java中的 swicth - case - default

<select id="getUser" resultType="com.cat.pojo.User">
  SELECT * FROM user 
  <where>
  <choose>
    <when test="id != null and test.trim() != '' ">
      id = #{id}
    </when> 
    <when test="name != null and name.trim() != '' ">
      name = #{name}
    </when> 
    <otherwise>
      age = 17  
    </otherwise>
  </choose>
</where>
</select>

七、resultMap標簽

在平時的開發中,我們沒有辦法一定能保證表中的字段名和表對應實體類的屬性名稱是完全相同的,resultMap可以解決表字段和實體屬性名不一致的問題
表結構

CREATE TABLE `user_info` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用戶id',
  `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用戶名',
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密碼',
  `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手機',
  `icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '頭像鏈接地址',
  `sex` int(5) NOT NULL DEFAULT '3' COMMENT '性別: 1 男,2 女, 3 保密',
  `age` int(5) NOT NULL DEFAULT '0' COMMENT '年齡',
  `birthday` bigint(15) DEFAULT '0' COMMENT '出生年月',
  `create_time` bigint(15) NOT NULL DEFAULT '0' COMMENT '創建時間',
  `update_time` bigint(15) NOT NULL DEFAULT '0' COMMENT '更新時間',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `index_name` (`user_name`) USING BTREE COMMENT '用戶名唯一索引',
  KEY `index_phone` (`phone`) USING BTREE COMMENT '手機號索引'
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='用戶表';

實體類

@Data
@Accessors(chain = true)
public class UserInfo implements Serializable {
    // 用戶id
    private Integer id;
    // 用戶名
    private String userName;
    // 密碼
    private String password;
    // 手機
    private String phone;
    // 頭像鏈接地址
    private String icon;
    // 性別: 1 男,2 女, 3 保密
    private Integer sex;
    // 年齡
    private Integer age;
    // 出生年月
    private Long birthday;
    // 創建時間
    private Long createTime;
    // 更新時間
    private Long updateTime;
    private static final long serialVersionUID = 1L;
}

可以看出數據庫字段一般是以下劃線的格式,而Java實體類是以駝峰格式,為了保證能正確映射,就需要使用resultMap標簽

 <resultMap id="BaseResultMap" type="com.gqlofe.userinfo.bean.entity.UserInfo">
   <id column="id" jdbcType="INTEGER" property="id" />
   <result column="user_name" jdbcType="VARCHAR" property="userName" />
   <result column="password" jdbcType="VARCHAR" property="password" />
   <result column="phone" jdbcType="VARCHAR" property="phone" />
   <result column="icon" jdbcType="VARCHAR" property="icon" />
   <result column="sex" jdbcType="INTEGER" property="sex" />
   <result column="age" jdbcType="INTEGER" property="age" />
   <result column="birthday" jdbcType="BIGINT" property="birthday" />
   <result column="create_time" jdbcType="BIGINT" property="createTime" />
   <result column="update_time" jdbcType="BIGINT" property="updateTime" />
 </resultMap>

 <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
   select 
   <include refid="Base_Column_List" />
   from user_info
   where id = #{id,jdbcType=INTEGER}
 </select>

使用resultMap將數據庫字段名和Java實體類屬性名一一映射,在查詢sql中使用resultMap=BaseResultMap,其中 BaseResultMap 是resultMap的id。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容

  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的...
    笨鳥慢飛閱讀 5,560評論 0 4
  • 前言 MyBatis是一個優秀的持久層ORM框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注SQL...
    AI喬治閱讀 641評論 0 5
  • mybatis中的sqlSession是線程安全的嗎? 鏈接:https://blog.csdn.net/qq_3...
    劉小刀tina閱讀 2,099評論 0 3
  • 百天培訓如期至, 未來前翹首企盼。 日思夜想這天來, 果真如期已來到。 培訓結果千千萬, 卻道不盡傷離別。 一別不...
    毛毛靜丫閱讀 162評論 2 3
  • 用柔軟的舌頭 捅破 天。
    風雨年輪閱讀 102評論 0 3