guanjian多表查询与单表查询的区别就在于:使用了连接查询,要自定义实体类
所以我们要做的是:
多表查询语句的使用
多表结果承接实体类设计
使用resultMap完成多表结果的映射
对一映射
package com.xin.pojo;
import lombok.Data;
@Data
public class Order {
private Integer orderId;
private String orderName;
private String customerId;
private Customer customer;
}
package com.xin.pojo;
import lombok.Data;
@Data
public class Customer {
private Integer customerId;
private String customerName;
}
关键词:
<association property="customer" javaType="com.xin.pojo.Customer">
相当于通过resultMap重新定义一个type对象,将平铺得查询结果可以存放到嵌套对象中
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.xin.mapper.OrderMapper">
<resultMap id="OrderMap" type="com.xin.pojo.Order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
<result column="customer_id" property="customerId"/>
<!-- 使用association标签配置“对一”关联关系 -->
<!-- property属性:在Order类中对一的一端进行引用时使用的属性名 -->
<!-- javaType属性:一的一端类的全类名 -->
<association property="customer" javaType="com.xin.pojo.Customer">
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
</association>
</resultMap>
<select id="selectById" resultMap="OrderMap">
select * from t_order o
left join t_customer c
on o.customer_id = c.customer_id
where order_id = #{orderId}
</select>
</mapper>
对多映射
package com.xin.pojo;
import lombok.Data;
@Data
public class Order {
private Integer orderId;
private String orderName;
private String customerId;
}
package com.xin.pojo;
import lombok.Data;
import java.util.List;
@Data
public class Customer {
private Integer customerId;
private String customerName;
private List<Order> orderList;
}
关键属性: <collection property="orderList" ofType="order">
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.xin.mapper.CustomerMapper">
<resultMap id="CustomerMap" type="com.xin.pojo.Customer">
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
<!-- collection标签:映射“对多”的关联关系 -->
<!-- property属性:在Customer类中,关联“多”的一端的属性名 -->
<!-- ofType属性:集合属性中元素的类型 -->
<collection property="orderList" ofType="com.xin.pojo.Order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
<result column="customer_id" property="customerId"/>
</collection>
</resultMap>
<select id="selectAll" resultMap="CustomerMap">
SELECT * from t_customer c
left join t_order o
on o.customer_id = c.customer_id
</select>
</mapper>
动态语句
wahere if标签
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.xin.mapper.CustomerMapper">
<resultMap id="CustomerMap" type="com.xin.pojo.Customer">
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
<collection property="orderList" ofType="com.xin.pojo.Order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
<result column="customer_id" property="customerId"/>
</collection>
</resultMap>
<select id="selectAll" resultMap="CustomerMap">
SELECT * from t_customer c
left join t_order o
on o.customer_id = c.customer_id
where
<!-- 使用if标签,让我们可以有选择的加入SQL语句的片段。这个SQL语句片段是否要加入整个SQL语句,就看if标签中test判断的结果是否为true -->
<!--为true,则进行sql拼接-->
<if test="orderId != null">
order_id = #{orderId}
</if>
<if test="orderNmae != null">
and order_name = #{orderNmae}
</if>
</select>
</mapper>
set标签
<update id="updte">
update t_customer set
<if test="orderNmae != null">
order_name = #{orderNmae},
</if>
<if test="customerId != null">
customer_id = #{customerId}
</if>
</update>
<!-- 存在两种问题:
1/两个IF都不满足,多了set关键字
2/第一个满足,第二个不满足,多了 ,
-->
<!--set标签可以动态去掉两端多余得逗号,但是无法解决第一种问题,所以要求set中至少有一个为true一-->
<update id="update">
update t_customer
<set>
<if test="orderNmae != null">
order_name = #{orderNmae},
</if>
<if test="customerId != null">
customer_id = #{customerId}
</if>
</set>
</update>
trim标签
- prefix属性:指定要动态添加的前缀
- suffix属性:指定要动态添加的后缀
- prefixOverrides属性:指定要动态去掉的前缀,使用“|”分隔有可能的多个值
- suffixOverrides属性:指定要动态去掉的后缀,使用“|”分隔有可能的多个值
<!-- List<Employee> selectEmployeeByConditionByTrim(Employee employee) -->
<select id="selectEmployeeByConditionByTrim" resultType="com.atguigu.mybatis.entity.Employee">
select emp_id,emp_name,emp_age,emp_salary,emp_gender
from t_emp
<!-- prefix属性指定要动态添加的前缀 -->
<!-- suffix属性指定要动态添加的后缀 -->
<!-- prefixOverrides属性指定要动态去掉的前缀,使用“|”分隔有可能的多个值 -->
<!-- suffixOverrides属性指定要动态去掉的后缀,使用“|”分隔有可能的多个值 -->
<!-- 当前例子用where标签实现更简洁,但是trim标签更灵活,可以用在任何有需要的地方 -->
<trim prefix="where" suffixOverrides="and|or">
<if test="empName != null">
emp_name=#{empName} and
</if>
<if test="empSalary > 3000">
emp_salary>#{empSalary} and
</if>
<if test="empAge <= 20">
emp_age=#{empAge} or
</if>
<if test="empGender=='male'">
emp_gender=#{empGender}
</if>
</trim>
</select>
choose/when/otherwise标签
在多个分支条件中,仅执行一个。
- 从上到下依次执行条件判断
- 遇到的第一个满足条件的分支会被采纳
- 被采纳分支后面的分支都将不被考虑
- 如果所有的when分支都不满足,那么就执行otherwise分支
<!-- List<Employee> selectEmployeeByConditionByChoose(Employee employee) -->
<select id="selectEmployeeByConditionByChoose" resultType="com.atguigu.mybatis.entity.Employee">
select emp_id,emp_name,emp_salary from t_emp
where
<choose>
<when test="empName != null">emp_name=#{empName}</when>
<when test="empSalary < 3000">emp_salary < 3000</when>
<otherwise>1=1</otherwise>
</choose>
<!--
第一种情况:第一个when满足条件 where emp_name=?
第二种情况:第二个when满足条件 where emp_salary < 3000
第三种情况:两个when都不满足 where 1=1 执行了otherwise
-->
</select>
foreach标签
批量操作
select/delete
List<Customer> queryBatch(@Param("ids") List<Integer> orderId);
<!--
collection属性:要遍历的集合
item属性:遍历集合的过程中能得到每一个具体对象,在item属性中设置一个名字,将来通过这个名字引用遍历出来的对象
separator属性:指定当foreach标签的标签体重复拼接字符串时,各个标签体字符串之间的分隔符,如果是最后一次不会追加
open属性:指定整个循环把字符串拼好后,字符串整体的前面要添加的字符串
close属性:指定整个循环把字符串拼好后,字符串整体的后面要添加的字符串
index属性:这里起一个名字,便于后面引用
遍历List集合,这里能够得到List集合的索引值
遍历Map集合,这里能够得到Map集合的key
-->
<select id="queryBatch" resultType="com.xin.pojo.Customer">
select * from t_customer where customer_id in
<foreach collection="ids" item="customerId" separator="," open="(" index="myIndex" close=")">
<!-- 在foreach标签内部如果需要引用遍历得到的具体的一个对象,需要使用item属性声明的名称 -->
#{customerId}
</foreach>
</select>
insert/update
<foreach collection="empList" item="emp" separator="," open="values" index="myIndex">
<!-- 在foreach标签内部如果需要引用遍历得到的具体的一个对象,需要使用item属性声明的名称 -->
(#{emp.empName},#{myIndex},#{emp.empSalary},#{emp.empGender})
</foreach>
sql片段
抽取重复的SQL片段
<!-- 使用sql标签抽取重复出现的SQL片段 -->
<sql id="mySelectSql">
select emp_id,emp_name,emp_age,emp_salary,emp_gender from t_emp
</sql>
引用已抽取的SQL片段
<!-- 使用include标签引用声明的SQL片段 -->
<include refid="mySelectSql"/>