目录
返回类型
resultType
resultMap
1、字段映射
2、多表查询
动态SQL
if标签
where标签
set标签
choose(when,otherwise) 语句
trim标签
for-each标签
SQL片段
返回类型
resultType
Mybatis在查询时,一定要指定返回类型;而其他操作,默认返回修改数目
在正常情况下,我们查询使用resultType返回查询结果是可以的
但是,也有其他情况是resultType不能解决的
如果说,类和数据库的参数不匹配,那么查询出来的结果在填充到类对象时,就会找不到对应的字段,(数据库的结果根据数据库列名和类字段名称进行匹配赋值)
数据库的列名是class_id,而类字段是 stu_class,mybatis不能将这两个联系起来,这时就需要使用resultMap
resultMap
1、数据库列名和类字段名称不匹配,可以使用resultMap来配置映射关系
2、resultMap可以用来处理多表联查
1、字段映射
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectById">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<resultMap id="Map" type="com.example.demo.Model.Student">
<!-- id标识这个resultMap,可以和数据库查找时id绑定,引用这个resultMap-->
<!-- type表示resultMap映射到的实体类-->
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="class_id" property="stu_class"></result>
<!-- id标识主键的映射 -->
<!-- result标识其他字段的映射-->
<!-- column表示数据库的字段,property表示类的字段,将数据库的列名和类字段联系起来-->
</resultMap>
<select id="selectById" resultMap="Map">
<!-- 这个id,表示实现StudentMapper接口的哪一个方法-->
<!-- resultMap 表示方法的返回类型,使用id绑定到上述的resultMap-->
select * from student where id=#{id}
<!-- 这里写具体的执行语句-->
</select>
</mapper>
这时,我们来运行单元测试:
2、多表查询
一个学生属于一个班级,一对一
1、创建Class类,Student类增加Class类的变量
@Data
public class Class {
private Integer class_id;
private String class_name;
}
@Data
public class Student {
private Integer id;
private String name;
private Integer class_id;
private Class stu_class;
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectAll">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<!-- Class类的映射-->
<resultMap id="classMap" type="com.example.demo.Model.Class">
<result column="class_id" property="class_id"></result>
<result column="class_name" property="class_name"></result>
</resultMap>
<resultMap id="StudentMap" type="com.example.demo.Model.Student">
<!-- id标识这个resultMap,可以和数据库查找时id绑定,引用这个resultMap-->
<!-- type表示resultMap映射到的实体类-->
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="class_id" property="class_id"></result>
<!-- id标识主键的映射 -->
<!-- result标识其他字段的映射-->
<!-- column表示数据库的字段,property表示类的字段,将数据库的列名和类字段联系起来-->
<!-- association实现一对一多表查询的映射关系 -->
<!-- id 表示Student类中创建的Class对象的变量名称,resultMap表示class类的映射关系,会将查询到的Class数据按照此形式填充
columnPrefix给数据库起别名,这样可以避免两个表有重名列时,数据重复的情况(第二个表id应该是2,第一个表id为1,因为同名,第二个表的id就变成了第一个表id的值 查询错误) -->
<association property="stu_class" resultMap="classMap" columnPrefix="c_">
</association>
</resultMap>
<select id="selectAll" resultMap="StudentMap">
<!-- 这个id,表示实现StudentMapper接口的哪一个方法-->
<!-- resultMap 表示方法的返回类型,使用id绑定到上述的resultMap-->
<!-- class表的属性重命名-->
select student.*,class.class_id c_class_id,class.class_name c_class_name from student,class where student.class_id=#{class_id} and class.class_id=#{class_id}
<!-- 这里写具体的执行语句-->
</select>
</mapper>
一个班级可以有多个学生 一对多
@Data
public class Student {
private Integer id;
private String name;
private Integer class_id;
}
@Data
public class Class {
private Integer class_id;
private String class_name;
private List<Student> list;
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectAllStudents">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<resultMap id="StudentMap" type="com.example.demo.Model.Student">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="class_id" property="class_id"></result>
</resultMap>
<!-- Class类的映射-->
<resultMap id="classMap" type="com.example.demo.Model.Class">
<result column="class_id" property="class_id"></result>
<result column="class_name" property="class_name"></result>
<collection property="list" resultMap="StudentMap" columnPrefix="s_"></collection>
<!-- property 绑定字段 将student表以s_重命名-->
</resultMap>
<select id="selectAllStudents" resultMap="classMap">
select class.*, student.id s_id,student.name s_name,student.class_id s_class_id from class,student where student.class_id=#{class_id} and class.class_id=#{class_id}
<!-- 这里写具体的执行语句-->
</select>
</mapper>
动态SQL
如果有比较复杂的业务,我们需要写复杂的 SQL 语句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。
那么怎么去解决这个问题呢?这就要使用 mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。
if标签
根据name和class_id来查询学生信息
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectStudent">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<select id="selectStudent" resultType="com.example.demo.Model.Student">
select * from student where name=#{name} and class_id=#{class_id}
</select>
</mapper>
如果class_id为空,那么就是select * from student where name=#{name} and class_id=null;
如果name为空,那么就是select * from student where name= and class_id=#{class_id};这是错误的写法,我们这时就要用到if标签
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectStudent">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<select id="selectStudent" resultType="com.example.demo.Model.Student">
select * from student where
<if test="name!=null">
name=#{name}
</if>
<if test="class_id!=null">
and class_id=#{class_id}
</if>
</select>
</mapper>
如果class_id为空,那么就是select * from student where name= #{name};
如果name为空,那么就是select * from student where and class_id=#{class_id};这是错误的写法,要使用到where标签
where标签
where标签就是为sql加上where关键字,且会自动的多余的and、or关键字,当所有的条件都不成立的时候,where标签也不会生成
去掉前面的and,不会去掉后面的and
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectStudent">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<select id="selectStudent" resultType="com.example.demo.Model.Student">
select * from student
<where>
<if test="name!=null">
name=#{name}
</if>
<if test="class_id!=null">
and class_id=#{class_id}
</if>
</where>
</select>
</mapper>
set标签
set元素会动态前置SET关键字,同时也会自动抹去where查询条件前多余的逗号,避免因为使用条件语句在生成赋值语句的后面留下不需要的逗号
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.UpdateStudent">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<update id="updateStudent" >
update student
<set>
<if test="id!=null">
id=#{id}
</if>
<if test="name!=null">
,name=#{name}
</if>
</set>
</update>
</mapper>
choose(when,otherwise) 语句
有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.SelectByChoices">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<select id="selectByChoices" resultType="com.example.demo.Model.Student">
select * from student where
<choose>
<when test= "id!=null">id=#{id}</when>
<when test="name!=null">name=#{name}</when>
<otherwise > class_id=#{class_id}</otherwise>
</choose>
</select>
</mapper>
when相当于if,otherwise相当于else
也就是说,这里我们有三个条件,id,name,class_id,只能选择一个作为查询条件
如果 id 不为空,那么查询语句为:select * from student where id=?
如果 id 为空,那么看name 是否为空,如果不为空,那么语句为 select * from student where name=?;
如果 name 为空,那么查询语句为 select * from student where class_id=?
trim标签
用于去掉某些内容
- prefix表示语句块,以prefix值为前缀
- suffix表示语句块,以suffix值为后缀
- prefixOverrides表示语句块,要去除的前缀
- suffixOverrides表示语句块,要去除的后缀
用 trim 改写上面的 if+where 语句
<select id="selectStudent" resultType="com.example.demo.Model.Student">
select * from student
<trim prefix="where" prefixOverrides="or|and">
<if test="name!=null">
name=#{name}
</if>
<if test="class_id!=null">
and class_id=#{class_id}
</if>
</trim>
<!-- trim prefix="where" prefixOverrides="or|and" 表示trim标签的语句内,拼接where,去除or、and前缀 -->
</select>
用 trim 改写上面的 set 语句
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.UpdateStudent">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<!-- <update id="updateStudent" >-->
<!-- update student-->
<!-- <set>-->
<!-- <if test="id!=null">-->
<!-- id=#{id}-->
<!-- </if>-->
<!-- <if test="name!=null">-->
<!-- ,name=#{name}-->
<!-- </if>-->
<!-- <trim prefix="" suffix="" prefixOverrides="" suffixOverrides="">-->
<!-- </trim>-->
<!-- </set>-->
<!-- </update>-->
<update id="updateStudent" >
update student
<trim prefix="set" prefixOverrides="," suffixOverrides=",">
<if test="id!=null">
id=#{id},
</if>
<if test="name!=null">
name=#{name},
</if>
</trim>
</update>
</mapper>
for-each标签
这样写的时候,就要多次 id=#{id},可以使用foreach标签实现循环
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.Mapper.DeleteSomeStudents">
<!-->namespace 绑定xml文件实现的接口 包名+类名 <-->
<!-- <delete id="delete" >-->
<!-- delete from student where id=#{id} or id=#{id1} or id=#{id2}-->
<!-- </delete>-->
<delete id="delete">
<!-- id绑定方法-->
delete from student
<where>
<!--
collection:指定输入对象中的集合 例如list,map,或者set 对象
item:每次遍历生成的对象 我们枚举时是id,id1,id2 而item类似于for循环的变量i
open:开始遍历时的拼接字符串
close:结束时拼接的字符串
separator:遍历对象之间需要拼接的字符串
delete from student where id=#{id} or id=#{id1} or id=#{id2}
-->
<foreach collection="list" item="id" open="(" close=")" separator="or">
<if test="id!=null">
id=#{id}
<!-- delete from student where ( id={#id} or id=#{id} or id=#{id} ) 这里的#{id}是循环遍历的值-->
</if>
</foreach>
</where>
</delete>
</mapper>
SQL片段
如果某一SQL的使用频率很高,我们可以把他单独定义,提供代码复用率
1、定义SQL
<sql id="selectStudentByTd_SQL">
select * from student
<where>
<if test="id!=null">
id=#{id}
</if>
</where>
</sql>
2、引用SQL
<select id="selectById" resultType="com.example.demo.Model.Student">
<!-- 如果refid 指定的不在本文件中,给引用前缀加上namespace,指定SQL片段所在文件 所对应的接口-->
<include refid="com.example.demo.Mapper.DeleteSomeStudents.selectStudentByTd_SQL"></include>
</select>