1.sql标签
公共sql块,一般用在查询字段上.
<sql id="allFields">
uid,uname,uemail,upwd,uphone,create_time,update_time
</sql>
在select标签中通过include包含sql块
<select id="selectByKey" resultType="sysuser">
select
<include refid="allFields"></include>
from sysuser where uid=#{uid}
</select>
2.resultMap标签(重要)
ResultMap标签使用起来偏复杂,用来对实体对象的属性与数据库字段名做映射,同时提供子标签做对象之间的关系映射,进行级联查询操作。
ResultMap 的设计思想是,对于简单的语句不需要配置显式的结果映射(属性名与字段名一致),而对于复杂一点的语句只需要描述它们的关系就行了。
结果集映射标签,把数据库中的字段名映射到某个实体类的成员变量.
<!-- id结果集名称 type结果集映射的实体类-->
<resultMap id="sysuserMap" type="sysuser">
<!--coleumn列名 property属性名-->
<id column="uid" property="uid"></id>
<result column="user_address" property="uaddress"/>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
</resultMap>
相同字段可以不写
如果字段名与属性名相同,可省了配置,但id不能省.一般都全部配置.
语句中使用resultMap在标签中的resultType更改成resultMap="sysuserMap"
<!--select标签的resultMap属性的值对应resultMap标签的id-->
<select id="selectUserById" parameterType="int" resultMap="sysuserMap">
select * from sysuser where uid=#{uid}
</select>
注意:
1.select标签的resultMap属性与resultType属性不能同时出现,resultType属性的值一般是实体类map或简单型;
2.resultMap属性的值必须是resultMap标签的id值。
3.resultMap标签的id子标签用来进行主键列映射;result子标签进行非主键列映射;
3.对象关系映射(重要)
对象之间的关系:分为持有和聚合
1.多对一持有关系(用个用户持有一个角色)
A对象持有B对象的引用,A类中有一个成员变量是B类型的.
比如:用户对象持有角色对象,查询用户的时候,查询出用户的角色信息.
方法1:手工进行两次的单表查询,第一次查询用户,第二次查询角色,把查询结果组合起来.掌握(建议)
- 创建SysuserMapper.java与sysuserMapper.xml
public interface SysuserMapper {
public Sysuser selectUserByKey(Integer uid);
}
<select id="selectUserByKey" parameterType="int" resultType="Sysuser">
select * from sysuser where uid=#{
uid}
</select>
- 创建SysroleMapper.java与sysroleMapper.xml
public interface SysroleMapper {
public Sysrole selectRoleByRid(Integer rid);
}
<select id="selectRoleByRid" parameterType="int" resultType="sysrole">
select * from sysrole where rid=#{
rid}
</select>
- 测试,结果组合
SysRoleMapper rm = session.getMapper(SysRoleMapper.class);
SysUserMapper2 um = session.getMapper(SysUserMapper2.class);
//第一次查询用户
Sysuser sysuser = um.selectUserByKey(13);
//第二次查询该用户的角色
Sysrole sysrole = rm.selectRoleByKey(sysuser.getRid());
//组装对象
sysuser.setSrole(sysrole);
方法2:由mybatis进行两次单表查询,使用association标签指定二次查询的位置.掌握(两个mapper.两个映射文件)
property:持有对象的变量名 column:传入二次查询的参数的字段
javaType:持有对象的类型 ,二次查询返回值的类型 select : 二次查询的位置(namespace+id )
<!--select:二次查询的位置namespace.id
srole:持有对象的变量名
javaType:持有对象的类型,二次查询的返回值类型
column:传入二次查询的字段,二次查询需要的参数
-->
<association property="srole" column="rid" javaType="sysrole"
select="com.javasm.mapper.SysroleMapper.selectByKey"></association>
<resultMap id="sysuserAndRoleMap" type="sysuser">
<id column="uid" property="uid"></id>
<result column="uname" property="uname"></result>
<result column="uemail" property="uemail"></result>
<result column="uphone" property="uphone"></result>
<result column="upwd" property="uped"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
<association property="srole" column="rid" javaType="sysrole" select="com.javasm.mapper.SysRoleMapper.selectRoleByKey">
</association>
</resultMap>
<select id="selectUserAndRoleByUKey" resultMap="sysuserAndRoleMap">
select * from sysuser where uid = #{uid}
</select>
//角色映射文件中
<select id="selectRoleByKey" parameterType="int" resultType="sysrole">
select * from sysrole where rid = #{rid}
</select>
方法3:使用sql语句表级联查询,一次需要的列全查出来,不需要进行二次查询.association
不推荐使用(单表操作索引生效,夺多表操作索引失效)复杂的报表分析可以使用(当使用在报表分析的时候直接返回map)
<resultMap id="sysuserAndRoleMap2" type="sysuser">
<id column="uid" property="uid"></id>
<result column="uname" property="uname"></result>
<result column="uemail" property="uemail"></result>
<result column="uphone" property="uphone"></result>
<result column="upwd" property="uped"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
<association property="srole" javaType="sysrole" >
<id column="rid" property="rid"></id>
<result column="rname" property="rname"></result>
<result column="rdec" property="rdec"></result>
<result column="roleCreateTime" property="createTime"></result>
<result column="roleUpdateTime" property="updateTime"></result>
</association>
</resultMap>
<select id="selectUserAndRoleByUKey2" resultMap="sysuserAndRoleMap2">
select u.*,r.rname,r.rdec,r.create_time,r.update_time as roleCreateTime,r.update_time as roleUpdateTime from sysuser u,sysrole r where u.rid=r.rid and u.uid=#{uid}
</select>
2.聚合关系(一个角色聚合了多个用户)
A对象持有了B对象的集合,A类中有一个List集合,集合泛型是B类型的.比如:角色对象聚合了用户对象,查询角色并查询出该角色下的所有用户信息.
使用collection标签进行聚合映射
方法1:手工进行两次的单表查询,把查询结果组合起来.掌握(建议)
方法2:由mybatis进行两次单表查询,使用association标签指定二次查询的位置.掌握(两个mapper.两个映射文件)
<resultMap id="roleAndUsersMap" type="sysrole">
<id column="rid" property="rid"></id>
<result column="rname" property="rname"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
<collection property="susers" ofType="sysuser" column="rid" select="com.javasm.mapper.SysUserMapper2.selectUsersByRoleId">
</collection>
</resultMap>
<select id="selectRoleAndUserByRid" resultMap="roleAndUsersMap" parameterType="int">
select * from sysrole where rid=#{rid};
</select>
//另外一个映射文件
<resultMap id="sysuserMap" type="sysuser">
<id column="uid" property="uid"></id>
<result column="uname" property="uname"></result>
<result column="uemail" property="uemail"></result>
<result column="uphone" property="uphone"></result>
<result column="upwd" property="upwd"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
</resultMap>
<select id="selectUsersByRoleId" parameterType="int" resultMap="sysuserMap">
select * from sysuser where rid=#{rid}
</select>
方法3:使用sql语句表级联查询,一次需要的列全查出来,不需要进行二次查询.collection
property:持有对象的变量名 javaType:只有两种list或者set
ofType:集合的泛型类型是什么 column:传入入二次查询的参数的字段
<!--ofType:集合的泛型类型-->
<collection property="susers" ofType="sysuser" column="rid" select="com.javasm.mapper.SysuserMapper2.selectUsersByRoleId"></collection>
<resultMap id="roleAndUsersMap2" type="sysrole">
<id column="rid" property="rid"></id>
<result column="rname" property="rname"></result>
<result column="create_time" property="createTime"></result>
<result column="update_time" property="updateTime"></result>
<collection property="susers" ofType="sysuser">
<id column="uid" property="uid"></id>
<result column="uname" property="uname"></result>
<result column="ctime" property="createTime"></result>
<result column="utime" property="updateTime"></result>
</collection>
</resultMap>
<select id="selectRoleAndUserByRid2" resultMap="roleAndUsersMap2" parameterType="int">
select r.*,u.uid,u.uname,u.uphone,u.uemail,u.create_time as ctime,
u.update_time as utime from sysrole r,sysuser u where r.rid=u.rid and r.rid =#{rid}
</select>
4.动态sql语句(重要)
在映射文件中进行sql语句拼接.
if/where标签
- if:用来做条件判断
- where:用来生成where关键字.
并忽略紧跟其后的and或or
如果if都为null或者’'那么这个where标签不会添加where
<select id="selectUsers" parameterType="sysuser" resultType="sysuser">
select uid,uname,uphone,upwd,uemail,create_time,update_time from sysuser
<where>
<if test="uname!=null and uname!=''">
and uname=#{uname}
</if>
<if test="uphone!=null and uphone!=''">
and uphone=#{uphone}
</if>
<if test="uemail!=null and uemail!=''">
and uemail=#{uemail}
</if>
<!-- 如果查询的字段是Intger类型则不用写and uphone!=''
<if test="uphone!=null">
uphone=#{uphone}
</if>-->
</where>
order by update_time desc
</select>
set标签
- set:用来生成set关键字,update语法.
并忽略最后的逗号,
<update id="updateUser" parameterType="sysuser">
update sysuser
<set>
/*修改不用写uname!=''因为可能前端想故意把字段写为''空*/
<if test="uname!=null">
uname=#{uname},
</if>
<if test="uphone!=null">
uphone=#{uphone},
</if>
</set>
where uid=#{uid}
</update>
foreach标签
- foreach:用来做批量删除
int delUsers(List<Integer> uids);批量删除,
=========================================================
方法一 | List<Integer> uids :mybatis底层把List封装成map,默认key是<list>
方法二 | Integer[] uids :mybatis底层把数组封装成map,默认key是<array>
方法三 | 用@Param("uids")注解自定义key
collection – 传递参数类型list/array/自定义key index – 循环索引
item – 集合中的元素 open –以什么开始; close – 以什么结束
<delete id="delUsers" parameterType="map">
DELETE FROM sysuser WHERE uid in
<foreach collection="list" open="(" close=")" item="uid_item" separator=",">
#{uid_item}
</foreach>
</delete>
- 批量增加
int addUsers(@Param("users") Sysuser[] users);
<insert id="addUsers" parameterType="map">
insert into sysuser(uname,uphone) values
<foreach collection="users" separator="," item="user">//没有开始和关闭,自己写
(#{user.uname},#{user.uphone})
</foreach>
</insert>
choose-when-otherwis标签
- choose-when-otherwise:单条件查询,没用.
只会有一个when条件成立如果没有一个when条件成立那么会执行otherwise标签内容
<select id="selectUsers2" parameterType="sysuser" resultType="sysuser">
select uid,uname,uphone,upwd,uemail,create_time,update_time from sysuser
<where>
<choose>
<when test="uname!=null and uname!=''">
and uname=#{uname}
</when>
<when test="uphone!=null and uphone!=''">
and uphone=#{uphone}
</when>
<otherwise>
1=1
</otherwise>
</choose>
</where>
order by update_time desc
</select>
5.mybatis的延迟加载,不重要
mybatis中的延迟加载仅在有二次查询的场景下生效.
延迟加载目的:减少无效的数据库查询操作,提高响应的效率.
延迟加载:分页,树形结构数据,前端图片的延迟加载
开启延迟加载时需要配置的setting
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--启用延迟加载-->
<setting name="lazyLoadingEnabled" value="true"></setting>
<!--消极加载,只有当调用二级查询的字段时才加载-->
<setting name="aggressiveLazyLoading" value="false"></setting>
<!-- value值从equals,clone,hashCode,toString中选取如果以上些行为均不想触发则写上空格-->
<setting name="lazyLoadTriggerMethods" value=""></setting>
6.mybatis缓存,不重要
cache:减少数据库的重复查询操作.基于内存把第一次查询的结果保存的缓存对象中,当后续查询时,先查询缓存,缓存中有则返回;缓存中没有则查询数据库,并把查询结果放缓存.
mybatis的缓存分为两级:
session级别缓存:默认开启.在同一个session会话中发起相同的查询.
factory级别缓存:默认未开启.可以做到不同会话之间共享缓存数据.
开启factory二级缓存的步骤
- 在配置文件中添加settings
<setting name="cacheEnabled" value="true"></setting>
- 在对应的映射文件中做缓存策略配置
<!--缓存策略,只对当前namespace下的所有查询全部生效,
可以在用户查询概率较少的select标签中加useCache="false"禁用二级缓存,
可以在update,delete中使用flushCache="true"强制清空缓存-->
<cache
eviction="FIFO" FIFO先进先出策略|LRU最近最少使用
flushInterval="60000" 60秒清楚所有缓存
size="512" 最大保存记录条数
readOnly="true"/> 只读