Mybatis
1.动态SQL
相当于按条件拼接SQL语句
**if 判断条件: ** 相当于java中的if语句
where 标签: 代替的where 1=1恒等式
如果where标签对中有子句拼接,where就提供一个where关键字
去掉第一个多余的and
如果where标签对中没有子句拼接,提供where关键字
<select id="queryEmp" resultType="Emp">
select empno,ename,job,mgr,sal,comm,hiredate,deptno from emp
<!--或者 where 1=1 恒等式 -->
<where>
<if test="ename!=null and ename!=''">
and ename = #{ename}
</if>
<if test="deptno!=null and deptno!=0">
and deptno = #{deptno}
</if>
</where>
</select>-->
set标签 : 自动去掉最后的,
<update id="updateEmp">
update emp
<set>
empno =#{empno},<!--没有满足条件的 前面要加上 和where判断一样的语句-->
<if test="ename!='' and ename!=null">
ename = #{ename},
</if>
<if test="sal!=null and sal!=0">
sal = #{sal},
</if>
</set>
where empno =#{empno}
</update>
trim标签:
使用trim代替where标签
用于在前后添加或删除一些内容
-
prefix,在前面添加内容
-
refixOverrides, 从前面去除内容
-
suffix, 向后面添加内容
-
uffixOverrides, 从后面去除内容
<select id="queryEmp" resultType="Emp"> select <include refid="emp_all"/> from emp <trim prefix="where" prefixOverrides="and"> <if test="ename!=null and ename!=''"> and ename = #{ename} </if> <if test="deptno!=null and deptno!=0"> and deptno = #{deptno} </if> </trim> </select>
choose when: 只能判断拼出一个条件类似 swtich case
<select id="queryEmp2" resultType="Emp">
select <include refid="emp_all"/> from emp
<where>
<choose> <!--switch-->
<when test="ename!='' and ename!=null"> <!--case-->
and ename = #{ename}
</when>
<when test="deptno!=0 and deptno!=null"> <!--case-->
and deptno = #{deptno}
</when>
<otherwise>and sal>1500</otherwise>
</choose>
</where>
</select>
bind :用于对数据进行再加工, 用于模糊查询
<if test="ename!=null and ename!=''">
<bind name="ename" value="'%' + ename + '%'" />
and ename like #{ename}
</if>
sql include: sql用于提取 SQL 语句, include用于引用 SQL 语句
<sql id="emp_all">
empno,ename,job,mgr,sal,comm,hiredate,deptno
</sql>
select <include refid="emp_all"/> from emp
使用动态sql后,如果接口中的参数名称不对应 必须用@Param注解改为对应的 不能使用arg0类似的
2.列名和属性名不一致问题
列别名
查询时, 可以通过列别名的方式将列名和属性名保持一致,继续使用自动映射, 从而解决该问题. 但是较为麻烦
使用resultMap
resultMap用于自定义映射关系, 可以由程序员自主制定列名和属性名的映射关系. 一旦使用 resultMap, 表示不再采用自动映射机制
<!--resultMap 自动映射关联设置
注意: 非同名的属性与字段之间必须 通过resultMap设置关联
如果同名可以省略
-->
<resultMap id="user_map" type="user">
<!--<id proerty='' column=''> 映射主键-->
<result property="name" column="username"/><!--映射非主键-->
</resultMap>
3.关系映射查询
数据库中表与表之间的关系:
一对一 (人->身份证)
一对多 (夏令营->学生)
多对一 (学生->班级)
多对多 (学生->课程)
resultMap 的关联方式实现多表查询(一对一|多对一)
通过resultMap标签定义映射关系, 并通过association标签指定对象属性的映射关系.
可以把association标签看成一个resultMap标签使用.
javaType 属性表示当前对象, 可以写全限定路径或别名
学生类中添加一个班级类型的属性
<!--做表字段与类型属性的映射-->
<resultMap id="haha" type="Emp">
<id property="empno" column="empno"></id>
<result property="ename" column="ename"/>
<result property="deptno" column="deptno"/>
<!--自定义引用数据类型的关联-->
<association property="dept" javaType="Dept">
<id property="deptno" column="deptno"/>
<result property="dname" column="dname"/>
<result property="loc" column="loc"/>
</association>
</resultMap>
resultMap 的关联方式实现多表查询(一对多)
通过resultMap定义映射关系, 并通过collection标签指定集合属性泛型的映射关系.
可以collection标签看成一个resultMap标签使用.
ofType 属性表示集合的泛型,可以写全限定路径或别名.
班级类中添加一个List容器存储学生类型的数据
<!--做表字段与类型属性的映射-->
<resultMap id="haha" type="Dept">
<id property="deptno" column="deptno"></id>
<result property="dname" column="dname"/>
<result property="loc" column="loc"/>
<!--设置当属性为集合类型时-->
<collection property="list" javaType="list" ofType="Emp">
<id property="empno" column="empno"/>
<result property="ename" column="ename"/>
<result property="deptno" column="deptno"/>
</collection>
</resultMap>
4.Mybates的缓存机制
一级缓存
-
默认开启. 线程级别的缓存, SqlSession 的缓存;
-
在一个 SqlSession 生命周期中有效. SqlSession 关闭,缓存清空;
-
在同一个 SqlSession 中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和结果存放在一个 Map 中,如果后续的键值一样,则直接从 Map中获取数据;
-
不同的 SqlSession 之间的缓存是相互隔离的;
-
用一个 SqlSession,可以通过配置使得在查询前清空缓存;flushCache=“true”
-
任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。
二级缓存
-
进程级别的缓存, SqlSessionFactory 的缓存
-
在一个SqlSessionFactory生命周期中有效. 可以在多个SqlSession 生命中期中共享.
-
默认关闭, 需要使用的时候, 要为某个命名空间开启二级缓存(在 mapper.xml 中配置cache)
-
由于在更新时会刷新缓存,因此需要注意使用场合:查询频率很高,更新频率很低时使用,即经常使用 select, 相对较少使用delete, insert, update。
-
缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响。但刷新缓存是刷新整个 namespace的缓存,也就是你 update 了一个,则整个缓存都刷新了。
-
最好在「只有单表操作」的表的 namespace 使用缓存,而且对该表的操作都在这个 namespace 中。否则可能会出现数据不一致的情况。
注解开发
MyBatis 中常用的注解
CRUD 注解
@Select: 类似于select标签
@Insert: 类似于insert标签
@Update: 类似于update标签
@Delete: 类似于delete标签
@Select("select * from dept")
List<Dept> queryDept();
@Select("select * from dept where deptno = #{deptno}")
Dept queryDeptByDeptno(int deptno);
@Update("update dept set dname = #{dname} where deptno = #{deptno}")
int updateDept(Dept dept);
其他注解
@Results: 类似于resultMap标签
@Result: 类似<resultMap的子标签
@One: 类似于association标签
@Many: 类似于collection标签
@Select("select * from emp")
@Results(value={
@Result(property ="empno",column = "empno",id = true), /*id = true主键字段*/
@Result(property ="ename",column = "ename"),
@Result(property ="deptno",column = "deptno"),
@Result(property ="dept",one=@One(select="com.xxxx.mappers.DeptMapper.queryDeptByDeptno"),column = "deptno")
})
List<Emp> queryEmp();
//class DeptMapper
@Select("select * from dept where deptno = #{deptno}")
Dept queryDeptByDeptno(int deptno);