动态SQL
MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力。 如果你有使用 JDBC 或其他 相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么的痛苦,确保不能忘了空 格或在列表的最后省略逗号。动态 SQL 可以彻底处理这种痛苦。
通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语 言来改进这种情形,这种语言可以被用在任意映射的 SQL 语句中。
动态 SQL 元素和使用 JSTL 或其他相似的基于 XML 的文本处理器相似。在 MyBatis 之 前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半 的元素就能工作了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
if
if 判断条件 相当于java中的if语句
where 标签 代替的where 1=1恒等式
如果where标签对中有子句拼接,where就提供一个where关键字
去掉第一个多余的and
如果where标签对中没有子句拼接,提供where关键字
接口:
List<Emp> queryEmpByName(@Param("ename") String ename, @Param("deptno") Integer deptno);
xml:
<select id="queryEmpByName" resultType="Emp" >
select * from emp where 1=1
<if test="ename!=null and ename!=''">
and ename = #{ename}
</if>
<if test="deptno!=null and deptno!=0">
and deptno = #{deptno}
</if>
</select>
java代码
List<Emp> list = mapper2.queryEmpByName("", 0);
list.forEach(System.out::println);
System.out.println("----------------");
list = mapper2.queryEmpByName("SMITH",0);
list.forEach(System.out::println);*/
where
用于管理 where 子句. 有如下功能:
- 如果没有条件, 不会生成 where 关键字
- 如果有条件, 会自动添加 where 关键字
- 如果第一个条件中有 and, 去除之
List<Emp> queryEmpWhere(@Param("ename") String ename, @Param("deptno") Integer deptno);
<select id="queryEmpWhere" resultType="Emp">
select * from emp
<where>
<if test="ename!=null and ename!=''">
and ename = #{ename}
</if>
<if test="deptno!=null and deptno!=0">
and deptno = #{deptno}
</if>
</where>
</select>
List<Emp> list = mapper2.queryEmpWhere("",10);
list.forEach(System.out::println);
choose…when…otherwise
功能类似于 switch…case…
List<Emp> queryEmpChoose(@Param("ename") String ename, @Param("deptno") Integer deptno);
<select id="queryEmpChoose" resultType="Emp">
select * from emp
<where>
<choose>
<when test="deptno!=null and deptno!=0">
and deptno = #{deptno}
</when>
<when test="ename!=null and ename!=''">
and ename = #{ename}
</when>
</choose>
</where>
</select>
List<Emp> list1 = mapper2.queryEmpChoose("KING",10);
list1.forEach(System.out::println);
set
用于维护 update 语句中的 set 子句. 功能如下:
- 满足条件时, 会自动添加 set 关键字
- 会去除 set 子句中多余的逗号
- 不满足条件时, 不会生成 set 关键字
<update id="queryEmpSet" >
update emp
<set>
empno = #{empno},
<if test="sal!=null and sal!=0">
sal = #{sal},
</if>
<if test="ename!=null and ename!=''">
ename = #{ename},
</if>
</set>
where empno = #{empno}
</update>
trim
使用trim代替where标签
用于在前后添加或删除一些内容
1. prefix, 在前面添加内容
2. prefixOverrides, 从前面去除内容
3. suffix, 向后面添加内容
4. suffixOverrides, 从后面去除内容
<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>
bind
用于对数据进行再加工, 用于模糊查询
<select id="queryEmpBind" resultType="Emp" parameterType="string">
select * from emp
<where>
<if test="ename!=null and ename!=''">
<bind name="ename" value="'%' + ename + '%'" />
and ename like #{ename}
</if>
</where>
</select>
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
resultMap
resultMap用于自定义映射关系, 可以由程序员自主制定 列名和属性名的映射关系. 一旦使用 resultMap, 表示不再 采用自动映射机制.
resultMap的id与select的resultMap值保持一致
<resultMap id="hh" type="Dept">
<id property="deptno" column="deptno"/>
<result property="dname" column="dname"/>
<result property="loc" column="loc"/>
</resultMap>
<select id="queryDept" resultMap="hh">
select * from dept
</select>
resultMap 的关联方式实现多表查询 (一对一|多对一)
- 在 StudentMapper.xml 中定义多表连接查询 SQL 语 句, 一次性查到需要的所有数据, 包括对应班级的信息.
- 通过resultMap标签定义映射关系, 并通过association 标签指定对象属性的映射关系. 可以把association标签 看成一个resultMap标签使用. javaType 属性表示当前 对象, 可以写全限定路径或别名.
emp类中添加一个dept类型的属性 :
<!--做表字段与类型属性的映射-->
<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>
<select id="queryEmp" resultMap="haha">
select empno,ename,e.deptno,dname,loc from emp e join dept d on e.deptno = d.deptno
</select>
resultMap 的关联方式实现多表查询 (一对 多)
在“一”的地方创建一个可以接受“多”的容器,把这个容器当作一个对象
在javabeen的dept类中添加一个List容器存储emp类型 的数据 :
/*存储部门所有的员工信息*/
List<Emp> list = null;
public List<Emp> getList() {
return list;
}
public void setList(List<Emp> list) {
this.list = 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>
<select id="queryDept" resultMap="haha">
select d.deptno,dname,loc,empno,ename from dept d left join emp e on e.deptno = d.deptno
</select>
public interface DeptMapper {
List<Dept> queryDept();
}
注意
-
接口的抽象方法与select的id要求保持一致
-
resultMap标签的id与 seselect中resultMap的value保持一致,
-
resultMap标签的type与 接口中List泛型保持一致,
-
collection标签中的ofType的值与javabeen中List泛型保持一致,
-
collection标签中的property=“list” javaType="list"与javabeen中返回值保持一致,
注解开发
CRUD 注解
- @Select: 类似于select标签
- @Insert: 类似于insert标签
- @Update: 类似于update标签
- @Delete: 类似于delete标签
用注解开发可以省略SQL映射文件,直接写在一个接口文件中,适用于简单的CRUD
@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")
})
@Select("select * from dept where deptno = #{deptno}")
Dept queryDeptByDeptno(int deptno);
点进去查看one注解为
public @interface One {
String select() default "";
FetchType fetchType() default FetchType.DEFAULT;
}
select 后面要为一个String类型,填写一个权限定类名加方法名查找到某条sql语句
tByDeptno"),column = “deptno”)
})
@Select(“select * from dept where deptno = #{deptno}”)
Dept queryDeptByDeptno(int deptno);
点进去查看one注解为
public @interface One {
String select() default “”;
FetchType fetchType() default FetchType.DEFAULT;
}
select 后面要为一个String类型,填写一个权限定类名加方法名查找到某条sql语句