先让我们看看mybatis常用动态SQL的标签有哪一些
如果mybatis和SSM整合环境不会搭建请看这篇
https://blog.csdn.net/weixin_44012722/article/details/105242601
我的数据库建表sql语句
create table student(
id int auto_increment PRIMARY KEY ,
name varchar(20) not null ,
department varchar(20) not null ,
sex varchar(10) not null ,
age int check(age>0)
);
create table `group`(
id int auto_increment PRIMARY KEY ,
name varchar(255) not null
);
create table student2group(
id int auto_increment PRIMARY KEY ,
stuid int not null,
groupid int not null
);
create table evaluate(
id int auto_increment PRIMARY KEY,
stuid int not null,
score int not null
);
1.insert,delete,update,select
这四个标签不用我多说了定义SQL语句的
注意这几个属性意思:
id:
resultType:输出结果类型
resultMap:输出结果结果映射
parameterType:输入接收参数类型
parameterMap:输入接收结果映射(一般很少用只有不写对象用Map接收参数的时候用,但是一般不写对象接收参数很难维护的 不能见名知意 可能会给队友后面的接盘侠 喷死)
2.reusltMap ,sql
结果集的一个映射
先简单看一下我的一个例子(这个常用在 结果集的映射和嵌套结果查询后面会讲)
mapper文件
<resultMap id="BaseResultMap" type="com.example.pojo.Student">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="department" jdbcType="VARCHAR" property="department" />
<result column="sex" jdbcType="VARCHAR" property="sex" />
<result column="age" jdbcType="INTEGER" property="age" />
</resultMap>
<sql id="Base_Column_List">
id, `name`, department, sex, age
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from student
where id = #{id,jdbcType=INTEGER}
</select>
<!--
①resultMap:
id:映射对象的主键
result -> column:数据库字段
->jdbcType:数据库类型
->property:映射对象的字段变量名
②sql:
通常是写复用的sql语句,如果有大量相同的sql语句出现可用它装起来
在需要此sql语句段地方用<include refid="sql标签的id" />引用即可
-->
测试类
@Test
public void test6(){
//使用元素查询特定id的部分学生信息
System.out.println("使用元素查询特定id的部分学生信息 :" + studentService.selectByPrimaryKey(3));
}
控制台结果
3.foreach
mapper文件
<select id="selectIDInScope" parameterType="java.util.List" resultType="com.example.pojo.Student">
select * from student where id in
<foreach collection="idScope" item="i" open="(" separator="," close=")">
${i}
</foreach>
</select>
<!--
collection:是接收参数的变量名,这个变量可以是一个集合或者数组
item:遍历集合或者数组的元素
open:开始内容
separator:间隔之间的内容
close:结束的内容
-->
测试类
@Test
public void test6_1(){
//使用元素查询特定id的部分学生信息
System.out.println("使用元素查询特定id的部分学生信息 :");
studentService.selectIDInScope(Arrays.asList(new Integer [] {1,2,3})).forEach(System.out::println);
}
控制台结果
4.if , trim
mapper文件
<insert id="insertSelective" parameterType="com.example.pojo.Student">
insert into student
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="name != null">
`name`,
</if>
<if test="department != null">
department,
</if>
<if test="sex != null">
sex,
</if>
<if test="age != null">
age,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=INTEGER},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="department != null">
#{department,jdbcType=VARCHAR},
</if>
<if test="sex != null">
#{sex,jdbcType=VARCHAR},
</if>
<if test="age != null">
#{age,jdbcType=INTEGER},
</if>
</trim>
</insert>
<!--
① if: test 判断语句(条件) 满足条件则加入if标签内的内容
② trim:在trim标签内的内容去除空格
prefix:开始的内容
suffix:结束的内容
suffixOverrides:结束内容前要去掉的内容
-->
测试类
@Test
public void test10(){
System.out.println("插入学生");
Student student = new Student();
student.setName("树懒");
student.setDepartment("计算机系");
student.setSex("男");
student.setAge(22);
System.out.println(studentService.insertSelective(student));
}
结果
5.choose,when,otherwise
<select id="selectActivityAnd" resultType="com.example.pojo.Student">
select
<include refid="Base_Column_List" />
from student where 1 = 1
<choose>
<when test="id != null ">
and id = #{id}
</when>
<when test="name != null and name != ''">
and name = #{name}
</when>
<when test="department != null and department != ''">
and department = #{department}
</when>
<when test="sex != null and sex != ''">
and sex = #{sex}
</when>
<otherwise>
and age > 20
</otherwise>
</choose>
</select>
<!--
choose和when以及otherwise要配合使用
when: test:判断语句(条件)满足条件则加入when标签内的内容
otherwise:choose内的when标签条件都不满足才加入otherwise标签内的内容
和 switch case default很像
注意:when 和 otherwise 标签内的内容都有一个and 所以要在choose标签的前面加上一个条件 1=1
-->
6.where,bind
mapper文件
<select id="selectByNameDim" resultType="com.example.pojo.Student">
<bind name="nameBind" value="'%'+name+'%'"/>
select
<include refid="Base_Column_List" />
from student
<where>
<if test="name != null and name != ''">
name LIKE #{nameBind}
</if>
</where>
</select>
<!--
bind标签作用:
在进行模糊查询时,如果使用“${}”拼接字符串,则无法防止 SQL 注入问题
。如果使用字符串拼接函数或连接符号,但不同数据库的拼接函数或连接
符号不同。例如 MySQL 的 concat 函数、Oracle 的连接符号“||”,这样
SQL 映射文件就需要根据不同的数据库提供不同的实现,显然比较麻烦,且不利
于代码的移植。幸运的是,MyBatis 提供了 <bind> 元素来解决这一问题。
bind -> name:绑定变量名
-> value:绑定的值 里面的name是我接收参数的变量名
是要在想用到的地方#{绑定的变量名}即可
where : 相当于给标签内部的内容前面加一个where关键字
-->
测试类
@Test
public void test7(){
//使用元素模糊查询学生信息
List<Student> students5 = studentService.selectByNameDim("大");
students5.forEach(System.out::println);
}
控制台结果
7.set
<update id="updateByPrimaryKeySelective" parameterType="com.example.pojo.Student">
update student
<set>
<if test="name != null">
`name` = #{name,jdbcType=VARCHAR},
</if>
<if test="department != null">
department = #{department,jdbcType=VARCHAR},
</if>
<if test="sex != null">
sex = #{sex,jdbcType=VARCHAR},
</if>
<if test="age != null">
age = #{age,jdbcType=INTEGER},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<!--
set:给set标签内的内容前面加上一个set关键字,where标签作用一样
-->
测试类
···java
@Test
public void test5(){
//使用元素实现学生信息的更新
Student condition4 = new Student();
System.out.println(“原本数据 :” + studentService.selectByPrimaryKey(1));
condition4.setId(1);
condition4.setName(“树懒”);
studentService.updateByPrimaryKeySelective(condition4);
System.out.println(“更新后数据 :” + studentService.selectByPrimaryKey(1));
}
···
控制台结果
8.association(用于一对一关系例如一个学生对应一个评估)
8.1嵌套查询
Student类添加一个evaluate成员变量
Student的mapper文件
<select id="selectStudentAndEvaluate" resultMap="studentEvalateMap">
select id, name, department, sex, age from student where id = #{id}
</select>
<resultMap id="studentEvalateMap" type="com.example.pojo.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="department" property="department"/>
<result column="sex" property="sex"/>
<result column="age" property="age"/>
<association property="evaluate" column="id" javaType="com.example.pojo.Evaluate" select="com.example.dao.EvaluateDao.selectByStuid" />
</resultMap>
<!--
association :
property:映射对象的成员变量的变量名
column:传给select查询语句的值
javaType:此关联查询对象的java类型
select:关联查询
-->
Evaluate的mapper文件
<select id="selectByStuid" resultType="com.example.pojo.Evaluate">
select id, score, stuid from evaluate where stuid = #{stuid}
</select>
测试类
@Test
public void test11(){
System.out.println("association 嵌套查询");
System.out.println(studentService.selectStudentAndEvaluate(1));
}
控制台结果
8.2嵌套结果
Student的mapper文件
<select id="selectStudentAndEvaluate2" resultMap="studentEvalateMap2">
select s.id,name,department,sex,age,e.id as eid,stuid,score from student s inner join evaluate e on s.id = e.stuid where s.id = #{id}
</select>
<resultMap id="studentEvalateMap2" type="com.example.pojo.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="department" property="department"/>
<result column="sex" property="sex"/>
<result column="age" property="age"/>
<association property="evaluate" javaType="com.example.pojo.Evaluate">
<id column="eid" property="id"/>
<result column="stuid" property="stuid"/>
<result column="score" property="score"/>
</association>
</resultMap>
<!--
association :
property:映射对象的成员变量的变量名
javaType:此关联查询对象的java类型
-->
测试类
@Test
public void test12(){
System.out.println("association 嵌套结果");
System.out.println(studentService.selectStudentAndEvaluate2(1));
}
控制台的结果
9.collection(用于一对多关系例如一个学生对应多个群组)
9.1嵌套查询
Student类添加一个groups成员变量
Student的mapper文件
<select id="selectStudentAndGroup" resultMap="findGroupResult">
select id,name,department,sex,age from student where id = #{id};
</select>
<resultMap id="findGroupResult" type="com.example.pojo.Student">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="department" property="department" />
<result column="sex" property="sex" />
<result column="age" property="age" />
<collection property="groups" ofType="com.example.pojo.Group" column="id" select="com.example.dao.GroupDao.findGroup"/>
</resultMap>
<!--
collection:
property:映射对象的成员变量的变量名
column:传给select查询语句的值
ofType:此关联查询对象的java类型
select:关联查询
-->
Group的mapper文件
<select id="findGroup" resultType="com.example.pojo.Group">
select id,name from `group` where id in ( select groupid from student2group where stuid = #{id} )
</select>
测试类
@Test
public void test8(){
System.out.println("collection 嵌套查询");
System.out.println(studentService.selectStudentAndGroup(1));
}
控制台的结果
9.2嵌套结果
Student的mapper文件
<select id="selectStudentAndGroup2" resultMap="studentMap">
select s.id,s.`name`,department,sex,age,g.id as gid,g.`name` as gname from student s inner join student2group ss on s.id = ss.stuid inner join `group` g on ss.groupid = g.id where s.id = #{id}
</select>
<resultMap id="studentMap" type="com.example.pojo.Student">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="department" property="department" />
<result column="sex" property="sex" />
<result column="age" property="age" />
<collection property="groups" ofType="com.example.pojo.Group">
<id column="gid" property="id" />
<result column="gname" property="name" />
</collection>
</resultMap>
<!--
collection:
property:映射对象的成员变量的变量名
ofType:此关联查询对象的java类型
-->
测试类
@Test
public void test9(){
System.out.println("collection 嵌套结果");
System.out.println(studentService.selectStudentAndGroup2(1));
}
控制台结果
总结
association是对一对一关系的关联查询
collection是对一对多关系的关联查询
他们用法属性相似 区别就在association的一个属性是javaType而collection的是ofType
对于多对多关系 Mybatis把它当做一对多来处理 所以不要过于追究。
关联查询又分为 嵌套结果 和 嵌套查询
从上面的例子可以看出 嵌套查询 是 拿着第一个SQL语句查询到的 字段 去作为查询条件执行第二个SQL语句 所以它是要经过两次SQL语句查询的
而 嵌套结果 是通过一个 连接表查询的SQL语句 把查询的结果字段 根据映射关系映射的结果集所以只用经过一个SQL语句查询
所以 嵌套查询 如果是数据库数据量大的不推荐使用 会拉低访问性能
10.插入数据返回主键
使用这三个属性,插入完成后将主键放入对象中
一键查询淘宝/拼多多内部优惠券,每日大额外卖红包,购物省钱的宝藏工具