1.mybatis返回主鍵的值:{
<insert id="XXX">
insert into sys_user(
id,user_name,user_password,user_email,
user_info,head_img,create_time
)
values(
#{id},#{userName},#{userPassword},#(userEmail),
#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
)
</insert>
·Mysql:{
1)適用于主鍵值自增(數(shù)據(jù)庫(kù)主鍵數(shù)據(jù)類型為int或者Long){
·修改配置文件
<insert id="XXX" useGeneratedKeys="true",keyProperty="id">
insert into sys_user(
id,user_name,user_password,user_email,
user_info,head_img,create_time
)
values(
#{id},#{userName},#{userPassword},#(userEmail),
#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
)
</insert>
·在對(duì)應(yīng)的接口中將方法的返回值設(shè)定為對(duì)應(yīng)的返回值。
}
2)適用于所有的情況:{
·修改配置文件
<insert id="XXX">
insert into sys_user(
id,user_name,user_password,user_email,
user_info,head_img,create_time
)
values(
#{id},#{userName},#{userPassword},#(userEmail),
#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
)
<selectKey keyColumn="id" resultType="long" keyProperty="id" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
</insert>
·在對(duì)應(yīng)的接口中將方法的返回值設(shè)定為對(duì)應(yīng)的返回值即可
}
}
Oracle:{
·修改配置文件
<insert id="XXX">
<selectKey keyColumn="id" resultType="long" keyProperty="id" order="BEFORE">
SELECT SEQ_ID.nextval from dual
</selectKey>
insert into sys_user(
id,user_name,user_password,user_email,
user_info,head_img,create_time
)
values(
#{id},#{userName},#{userPassword},#(userEmail),
#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
)
</insert>
·在對(duì)應(yīng)的接口中將方法的返回值設(shè)定為對(duì)應(yīng)的返回值即可
}
注意:類似于Mysql第二種方式补疑,或者是Oracle的返回主鍵值的方式<selectKey>標(biāo)簽執(zhí)行的順序僅僅和改標(biāo)簽配置的
order屬性值相關(guān)晕拆,和它在insert語(yǔ)句的前后順序無(wú)關(guān);
其他一些支持逐漸自增數(shù)據(jù)庫(kù)配置selectKey中回寫主鍵的sql可查閱《Mybatis從入門到精通 劉增輝著》第二章,p42.
}
2.使用map或者@Param注解來(lái)解決多個(gè)接口參數(shù)的問(wèn)題{
·當(dāng)接口對(duì)應(yīng)的方法中只有一個(gè)參數(shù)時(shí)耘拇,Mybatis并不關(guān)心參數(shù)叫什么名字就會(huì)把這個(gè)唯一的參數(shù)值拿來(lái)使用;
·當(dāng)接口對(duì)應(yīng)的方法中有多個(gè)入?yún)r(shí),若沒有使用@Param注解來(lái)標(biāo)識(shí)參數(shù)名,那么Mybatis默認(rèn)可用的參數(shù)名只有
[0,1,param1,param2]
·當(dāng)多接口參數(shù)中使用了@Param注解來(lái)標(biāo)識(shí)參數(shù)名丢间,那么Mybatis便可識(shí)別對(duì)應(yīng)在注解中標(biāo)識(shí)的參數(shù).
}
3.mybatis 模糊查詢(like):{
·普通SQL
<select id="XXX">
select *
from sys_user u
where u.user_name like concat('%',#{userName},'%')
and u.user_email=#{userEmail}
</select>
·動(dòng)態(tài)SQL
<select id="XXX">
select *
from sys_user u
where 1=1
<if test="userName !=null and userName!='' ">
and u.user_name like concat('%',#{userName},'%')
</if>
<if test"userEmail!=null and userEmail!='' ">
and u.user_email = #{userEmail}
</if>
</select>
}
4.動(dòng)態(tài)SQL:{
1)if{
·在where子句中使用if(例如上述筆記的like模糊查詢)
·在UPDATE中使用if{
<update id="XXX">
update sys_user
set
<if test="userName!=null and userName!='' ">
user_name = #{userName},
</if>
<if test="userPassword!=null and userPassword!='' ">
user_password = #{userPassword},
</if>
<if test="userEmail!=null and userEmail!='' ">
user_email = #{userEmail},
</if>
<if test="userInfo!=null and userInfo!='' ">
user_info = #{userInfo},
</if>
<if test="headImg!=null">
head_img = #{headImg,jdbcType=BLOB},
</if>
id = #{id}
where id=#{id}
</update>
}
·在INSERT動(dòng)態(tài)插入中使用if:{
<insert id="XXX" useGeneratedKeys="true" keyProperty="id">
insert into sys_user(
id,user_name,user_password,
<if test="userEmail!=null and userEmail!=''">
user_email,
</if>
user_info,head_img,create_time
)
values(
#{id},#{userName},
<if test="userEmail!=null and userEmail!=''">
#(userEmail),
<if>
#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbdType=TIMESTAMP}
)
</insert>
}
}
2)choose提供if...else、if...else...的邏輯:{
需求:當(dāng)參數(shù)id有值的時(shí)候優(yōu)先使用id進(jìn)行查詢驹针,當(dāng)id沒有值的時(shí)候就判斷userName是否有值烘挫,如果用戶名有值
就使用用戶名查詢,如果用戶名也沒有值那就使SQL查詢無(wú)結(jié)果柬甥。
<select id="XXX">
select *
from sys_user u
where 1=1
<choose>
<when test="id !=null">
and id= #{id},
</when>
<when test="userName !=null and userName!=''">
and user_name= #{userName},
</when>
<otherwise>
and 1=2
</otherwise>
</choose>
</select>
}
3)where饮六、set、trim{
1)where{
<select id="xxx">
select *
from sys_user
<where>
<if test="userName!=null and userName!=''">
and user_name = #{userName}
</if>
<if test="userEmail!=null and userEmail!=''">
and user_email = #{userEmail}
</if>
</where>
</selcet>
注意:使用<where>標(biāo)簽苛蒲,當(dāng)所有的if條件都不滿足的時(shí)候卤橄,最終生成的SQL語(yǔ)句中不會(huì)出現(xiàn)where子句,這就保證了
程序中永遠(yuǎn)不會(huì)出現(xiàn)where 1= 1 這樣的情況臂外;
where元素內(nèi)容就是以and開頭的條件窟扑,where會(huì)自動(dòng)去掉開頭的and.
}
2)set{
<update id="xxx">
update sys_user
<set>
<if test="userName!=null and userName!=''">
user_name = #{userName},
</if>
<if test="userPassword!=null and userPassword!=''">
user_name = #{userName},
</if>
<if test="userEmail!=null and userEmail!=''">
user_email = #{userEmail},
</if>
<if test="userInfo!=null and userInfo!=''">
user_info = #{userInfo},
</if>
id = #{id}
</set>
where id =#{id}
</updae>
注意:如果set標(biāo)簽包含的元素有返回值,就插入一個(gè)set;
如果set后面的字符串是以逗號(hào)結(jié)尾的漏健,就將這個(gè)逗號(hào)剔除;
如果set中的元素沒有內(nèi)容嚎货,那么生成的SQL還是會(huì)有SQL語(yǔ)法錯(cuò)誤,故此類似id=#{id}這樣的賦值任然還有必要保留
}
3)trim{
<trim prefix="WHERE" prefixOverrides="AND |OR">
...
</trim>
trim標(biāo)簽有如下的屬性:
prefix:當(dāng)trim元素內(nèi)包含內(nèi)容時(shí)蔫浆,會(huì)給內(nèi)容增加prefix指定的前綴殖属。
prefixOverrides:當(dāng)trim元素包含內(nèi)容時(shí),會(huì)把內(nèi)容中匹配的前綴字符串去掉瓦盛。
suffix:當(dāng)trim元素內(nèi)包含內(nèi)容時(shí)洗显,會(huì)給內(nèi)容增加suffix指定的后綴。
suffixOverrides:當(dāng)trim元素包含內(nèi)容時(shí)原环,會(huì)把內(nèi)容中匹配的后綴字符串去掉挠唆。
}
}
4)foreach{
foreach實(shí)現(xiàn)in集合:{
<select id="xxx">
select *
from sys_user
where id in
<foreach collection="list" open="(" close=")" separator="," item="id" index="i">
#{id}
</foreach>
</select>
}
注意:
·當(dāng)只有一個(gè)數(shù)組參數(shù)或者一個(gè)結(jié)婚參數(shù)的時(shí):
當(dāng)參數(shù)類型為集合(Collection)類型時(shí),默認(rèn)在Mybatis底層會(huì)將其轉(zhuǎn)換為Map類型,并添加
一個(gè)key為collection的值扮念;
當(dāng)參數(shù)是一個(gè)list集合類型時(shí)损搬,也會(huì)默認(rèn)轉(zhuǎn)換成map類型,默認(rèn)的key為list;
當(dāng)參數(shù)類型為數(shù)組時(shí),也會(huì)默認(rèn)轉(zhuǎn)換成map類型巧勤,默認(rèn)的key為array.
·有多個(gè)參數(shù):
使用@Param注解來(lái)給每個(gè)參數(shù)指定一個(gè)名字嵌灰,將collection的值設(shè)置為@Param指定的注解的名稱即可.
·參數(shù)是Map類型:
使用Map類型和使用@Param注解的情形類似只要將map的key的值綁定給collection的屬性即可;
如果要循環(huán)所輸入的Map,推薦使用@Param注解指定名字颅悉,此時(shí)可以將collection的值設(shè)置為@Param注解指定的名字即可沽瞭,如果不想指定名字,則使用_parameter.
·參數(shù)是一個(gè)對(duì)象:
這種情況下指定collection屬性值為對(duì)象的屬性名即可,當(dāng)使用對(duì)象內(nèi)多層嵌套的對(duì)象時(shí)剩瓶,使用屬性.屬性(集合和數(shù)組可以使用下標(biāo)取值),可以指定深層次的屬性值.
foreach實(shí)現(xiàn)批量插入:{
<insert id="XXX" useGeneratedKeys="true" keyProperty="id">
insert into sys_user(
user_name,user_password,user_email,
user_info,head_img,create_time
)
values
<foreach collection="list" item="user" separator=",">
(
#{userName},#{userPassword},#{userEmail},
#{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP}
)
</foreach>
</insert>
}
foreach實(shí)現(xiàn)動(dòng)態(tài)update:{
<update id="xxx">
update sys_user
set
<foreach collection="_parameter" item="val" index="key" separator=",">
${key}= #{val}
</foreach>
</update>
注意:當(dāng)參數(shù)為map類型時(shí)驹溃,foreach標(biāo)簽的index屬性值對(duì)應(yīng)的不是索引值,而是map中的key;
如上以map的key作為列名延曙,對(duì)應(yīng)的值作為該列的值豌鹤,通過(guò)foreach將需要更新的字段拼接在SQL語(yǔ)句中。
}
}
5)bind用法:{
·bind可以使用OGNL創(chuàng)建一個(gè)變量并將其綁定到上下文中枝缔;
·例子:修改之前的like模糊查詢:{
未修改之前:{
<if test="userName!=null and userName!=''">
and user_name like concat('%',#{userName},'%')
</if>
}
在未修改之前的版本中為使用like模糊查詢布疙,使用了concat函數(shù)來(lái)實(shí)現(xiàn)字符串拼接,在MySql中這個(gè)函數(shù)支持多個(gè)參數(shù),但是在Oracle中這個(gè)函數(shù)
只支持兩個(gè)參數(shù);由于不同數(shù)據(jù)庫(kù)之間語(yǔ)法的差異愿卸,如果更換數(shù)據(jù)庫(kù)灵临,有些SQL語(yǔ)句就可能需要重寫,針對(duì)這種情況可以使用bind標(biāo)簽來(lái)避免由于
更換數(shù)據(jù)庫(kù)而帶來(lái)的麻煩趴荸。
修改后:{
<if test="userName!=null and userName!='' ">
<bind name="userNameLike" value="'%'+userName+'%'"/>
and user_name like #{userNameLike}
</if>
注意:bind標(biāo)簽的兩個(gè)屬性都是必選項(xiàng)儒溉,name為綁定到上下文的變量名,value為OGNL表達(dá)式发钝。
}
}
}
}
5.mybatis二級(jí)緩存配置:{
}
6.mybatis高級(jí)映射:{
1)mybatis單表查詢:{
·單表查詢時(shí)可以使用字段別名來(lái)實(shí)現(xiàn)查詢返回結(jié)果集和JavaBean的映射;
·可以通過(guò)配置resultMap來(lái)實(shí)現(xiàn)映射;
·如果數(shù)據(jù)庫(kù)字段和JavaBean符合轉(zhuǎn)駝峰規(guī)則顿涣,通過(guò)在mybatis中配置全局屬性:
<settings>
<!--
通過(guò)將該屬性配置為true可以自動(dòng)將以下劃線方式命名的數(shù)據(jù)列映射到Java對(duì)象的駝峰式命名屬性中,
該屬性默認(rèn)值為false笼平,如果想要使用該功能园骆,需要手動(dòng)指配其值為true。
-->
<setting name="mapUnderscoreToCamelCase" value="true" />
<!--其他配置-->
</settings>
}
2)一對(duì)一映射:{
eg:{
package com.hsun.mybatis.model.SysUser;
public class User{
private String userName;
private String userPassword;
private SysRole role;//SysRole是一個(gè)實(shí)體類
//setter寓调、getter
}
·使用別名映射
<select id="xxx">
selcet
u.user_name,
u.user_password,
r.id "role.id",
r.role_name "role.roleName"
from sys_user u
inner join sys_user_role ur on u.id = ur.user_id
inner join sys_role r on ur.role_id = r.id
where u.id = #{id}
</selcet>
注意:上述方法中sys_role 查詢列的別名都是"role."前綴锌唾,通過(guò)這種方式,將role的屬性都映射到了
SysUser的role屬性上夺英。
·使用resultmap映射
<resultMap id="userAndRoleResultMap" type="com.hsun.mybatis.model.SysUser">
<id property="id" column="id" />
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<!--sys_role相關(guān)屬性-->
<result property="role.id" column="role_id" />
<result property="role.roleName" column="role_name" />
</resultMap>
注意:該種配置在property屬性中使用“role."前綴晌涕,column部分為了避免不同表中存在相同的列,所有可能重名
的列都加了"role_"前綴痛悯,使用這種配置的時(shí)候還要在查詢時(shí)使用不同的別名余黎。查詢語(yǔ)句如下:
<select id="xxx" resultMap="userAndRoleResultMap">
selcet
u.user_name,
u.user_password,
r.id role_id,
r.role_name
from sys_user u
inner join sys_user_role ur on u.id = ur.user_id
inner join sys_role r on ur.role_id = r.id
where u.id = #{id}
</selcet>
·使用resultMap標(biāo)簽的association標(biāo)簽來(lái)配置一對(duì)一映射
<!--userResultMap僅僅配置了user的屬性不包含role屬性-->
<resultMap id="userAndRoleWithAssociationResultMap" extends="userResultMap"
type="com.hsun.mybatis.model.SysUser">
<id property="id" column="id" />
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<association property="role" javaType="com.hsun.mybatis.model.SysRole"
columnPrefix="role_">
<!--sys_role相關(guān)屬性-->
<result property="id" column="role_id" />
<result property="roleName" column="role_name" />
</association>
</resultMap>
注意:
·property:實(shí)體類中的屬性名,必選項(xiàng)载萌,
·javaType:屬性對(duì)應(yīng)的Java類型惧财。
·resultMap:可以使用現(xiàn)有的resultMap巡扇,而不需要在association標(biāo)簽中配置result
·columnPrefix:查詢列的前綴,配置前綴后垮衷,在子標(biāo)簽result的column可以省略前綴厅翔。
但是在查詢時(shí),role對(duì)應(yīng)的查詢列都要使用別名并且別名必須是以此處配置的前綴開頭的搀突。
·在mybatis中不同命名空間下的resultMap也是可以引用的刀闷,引用時(shí)需要加上”命名空間.resultMap的id屬性“
例如:有關(guān)role的屬性全部配置到RoleMapper.xml 文件中,其中有一個(gè)resultMap的id為roleMap仰迁,那么在
UserMapper.xml文件中引用的方式如下:
<resultMap id="userAndRoleWithAssociationResultMap" extends="userResultMap"
type="com.hsun.mybatis.model.SysUser">
<id property="id" column="id" />
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<association property="role" resultMap="com.hsun.mybatis.model.RoleMapper.roleMap"
columnPrefix="role_" />
</resultMap>
}
·association標(biāo)簽嵌套查詢:{
·association標(biāo)簽的嵌套查詢常用的屬性如下:{
select:另一個(gè)映射查詢的id,mybatis會(huì)額外執(zhí)行這個(gè)查詢獲取嵌套對(duì)象的結(jié)果.
column: 列名(或別名)甸昏,將主查詢中列的結(jié)果作為嵌套查詢的參數(shù),配置方式如:
column={prop1=col1徐许,prop2=col2}施蜜,prop1,prop2將作為嵌套查詢的參數(shù).
·fetchType:數(shù)據(jù)加載方式绊寻,可選值為lazy和eager花墩,分別為延遲加載和積極加載悬秉,這個(gè)配置
會(huì)會(huì)覆蓋全局的lazyLoadingEnabled配置澄步。
<resultMap id="xxx" extends="userMap" type="com.hsun.mybatis.model.User">
<association property="role"
fetchType="lazy"
selcet="com.hsun.mybatis.mapper.RoleMapper.selcetRoleById"
column="id={role_id}">
</association>
<resultMap/>
}
}
}
3)一對(duì)多映射:{
使用collection集合的嵌套映射:
<resultMap id="userRoleListMap" extends="userResultMap"
type="com.hsun.mybatis.model.SysUser">
<id property="id" column="id" />
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<collection property="roleList" ofType="com.hsun.mybatis.model.SysRole"
columnPrefix="role_">
<!--sys_role相關(guān)屬性-->
<result property="id" column="role_id" />
<result property="roleName" column="role_name" />
</collection>
</resultMap>
或者:
<resultMap id="userRoleListMap" extends="userResultMap"
type="com.hsun.mybatis.model.SysUser">
<id property="id" column="id" />
<result property="userName" column="user_name"/>
<result property="userPassword" column="user_password"/>
<collection property="roleList" ofType="com.hsun.mybatis.model.SysRole"
columnPrefix="role_" resultMap="com.hsun.mybatis.mapper.SysRoleMapper.roleMap">
</collection>
</resultMap>
}
}
7.mybatis 部分常用settings配置:{
<settings>
<!--
通過(guò)將該屬性配置為true可以自動(dòng)將以下劃線方式命名的數(shù)據(jù)列映射到Java對(duì)象的駝峰式命名屬性中,
該屬性默認(rèn)值為false和泌,如果想要使用該功能村缸,需要手動(dòng)指配其值為true。
-->
<setting name="mapUnderscoreToCamelCase" value="true" />
<!--指定使用LOG4J來(lái)支持mybatis的日志-->
<setting name="logImpl" value="LOG4J" />
<!--
mybatis 二級(jí)緩存全局開關(guān)武氓,默認(rèn)為開啟狀態(tài),mybatis的二級(jí)緩存是和命名空間綁定的梯皿,即二級(jí)緩存需要配置在Mapper.xml、
文件中或者配置在Mapper.java接口中县恕。配置在xml文件中东羹,命名空間就是xml根節(jié)點(diǎn)mapper的namespace屬性。在mapper接口中忠烛,
命名空間就是接口的全限定名稱属提。
-->
<setting name="cacheEnabled" value="true" />
<!--
·該屬性是控制mybatis帶有延遲加載屬性的對(duì)象的完整加載或者延遲加載;
·當(dāng)改該屬性的值為true時(shí),會(huì)使得對(duì)任意延遲屬性的調(diào)用會(huì)使帶有延遲加載屬性的對(duì)象完整加載:
·當(dāng)該屬性的值為false時(shí)美尸,會(huì)對(duì)帶有延遲加載屬性的對(duì)象按需加載;
·該屬性的默認(rèn)值是true,故而要使用mybatis的延遲加載屬性需要手動(dòng)在<settings>標(biāo)簽中將該值配置為false;
·mybatis的延遲加載是通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)的冤议,在與spring集成時(shí),要確保帶有延遲加載的屬性的對(duì)象的獲取在
service層师坎。當(dāng)結(jié)果從service層返回controller層時(shí)恕酸,如果獲取延遲加載的屬性值,會(huì)因?yàn)镾qlSession已經(jīng)關(guān)閉而拋出異常.
-->
<setting name="agressivelazyLoading" value="false" />
</settings>
}