一、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。