Mybatis多表映射+动态语句

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 &gt; 3000">
            emp_salary>#{empSalary} and
        </if>
        <if test="empAge &lt;= 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 &lt; 3000">emp_salary &lt; 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"/>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值