Mybatis的高级查询&批量删除&批量添加

本文介绍了Mybatis的高级查询技巧,包括如何进行映射Mapper配置,实现动态SQL以进行批量删除和添加。此外,详细讨论了多对一和一对多的关系映射,以及嵌套结果和查询的处理方法。最后,还涉及了Mybatis的缓存机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、映射Mapper

接口方法映射到对应的SQL
XXXMapper.xml的命名空间名称就是Mapper接口的全限定名
Mapper接口上也可以通过相应的注释来写SQL(但是最好不要这么写哦)

//    查询全部
//    @Select("select * from employee")
    List<Employee> findAll();

employeeMapper.xml

<?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="cn.cxm.mapper.mapper.EmployeeMapper">
    <select id="findOne" parameterType="long" resultType="cn.cxm.mapper.domain.Employee">
        SELECT * FROM employee WHERE id=#{id}
    </select>

    <select id="findAll" parameterType="long" resultType="cn.cxm.mapper.domain.Employee">
        SELECT * FROM employee
    </select>
    <insert id="save" parameterType="cn.cxm.mapper.domain.Employee" >
        INSERT INTO employee (name,age) VALUES (#{name},#{age})
    </insert>

<!--
    <update id="update" parameterType="cn.cxm.mapper.domain.Employee">
        UPDATE employee SET name=#{name},age=#{age} WHERE id=#{id}
    </update>
-->

    <delete id="delete" parameterType="long">
        DELETE FROM employee WHERE id=#{id}
    </delete>
    <!--
    添加多条数据
    使用foreach标签,collection:遍历的集合,item:集合的每一个元素
    separator:分离符
    -->
    <insert id="batchSave" parameterType="list">
        INSERT INTO employee (name,age) VALUES
        <foreach collection="list" item="emp" separator=",">
            (#{emp.name},#{emp.age})
        </foreach>
    </insert>

    <!--批量删除,删除一定范围,使用in( ,)-->
    <delete id="batchDelete" parameterType="list">
        DELETE FROM employee WHERE id in
        <foreach collection="list" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

    <!--模糊查询-->
<!--
    <select id="queryAll" parameterType="list" resultType="cn.cxm.mapper.domain.Employee">
        SELECT * FROM employee where name LIKE CONCAT("%",#{name},"%")
    </select>
-->
<!--使用where标签,自动将第一个and替换为where-->
    <!--多条件查询-->
    <select id="queryAll" parameterType="cn.cxm.mapper.query.EmployeeQuery" resultType="cn.cxm.mapper.domain.Employee">
        SELECT * FROM employee
        <where>
            <if test="name!=null and name!=''">
                AND name LIKE CONCAT("%",#{name},"%")
            </if>
            <if test="minAge!=null">
                AND age>=#{minAge}
            </if>
            <if test="maxAge!=null">
                AND <![CDATA[ age<=#{maxAge}]]>
            </if>
        </where>
    </select>

    <!--查询总条数-->
    <select id="count" parameterType="cn.cxm.mapper.query.EmployeeQuery" resultType="long">
        SELECT count(id) FROM employee
            <where>
                <if test="name!=null and name!=''">
                    AND name LIKE CONCAT("%",#{name},"%")
                </if>
                <if test="minAge!=null">
                    AND age>=#{minAge}
                </if>
                <if test="maxAge!=null">
                    AND <![CDATA[ age<=#{maxAge}]]>
                </if>
            </where>
    </select>

    <!--动态修改,当使用动态修改,只修改其中的一条数据,同一id的其他数据不会改变-->
    <update id="update" parameterType="cn.cxm.mapper.domain.Employee">
        UPDATE employee
        <set>
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="age!=null">
            age=#{age},
            </if>
        </set>
        WHERE id=#{id}
    </update>
</mapper>

EmployeeMapper

package cn.cxm.mapper.mapper;

import cn.cxm.mapper.domain.Employee;
import cn.cxm.mapper.query.EmployeeQuery;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface EmployeeMapper {
//    添加
    void save(Employee employee);
//    删除
    void delete(Long id);
//    修改
    void update(Employee employee);
//    查询一条
    Employee findOne(Long id);
//    查询全部
//    @Select("select * from employee")
    List<Employee> findAll();
//    批量添加
    void batchSave(List<Employee> employee);
//    批量删除
    void batchDelete(List<Long> id);
//  高级查询之模糊查询
//  List<Employee> queryAll(String name);
//  高级查询之多条件查询
    List<Employee> queryAll(EmployeeQuery query);

//  查询总条数
    Long count(EmployeeQuery query);
}

调用 Mapper的方法

  @Test
    public void save() throws Exception{
        SqlSession session = MybatisUtil.getSession();
        EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
        Employee employee = new Employee();
        employee.setName("大蛇丸");
        employee.setAge(123);
        mapper.save(employee);
        session.commit();
    }

二.高级查询

准备一个Query对象(封装所有条件)
模糊查询 concat("%",#{name},"%")
遇到特殊符号 1.转义 &lt; 2.CDATA段 <![CDATA[...]]>
使用where标签(第一个and变成where)
if中有多个条件使用 and/or 进行关联
如果出现相就的代码,可以单独抽取sql标签,引用include即可

.employeeMapper.xml

  <!--模糊查询-->
<!--
    <select id="queryAll" parameterType="list" resultType="cn.cxm.mapper.domain.Employee">
        SELECT * FROM employee where name LIKE CONCAT("%",#{name},"%")
    </select>
-->
<!--使用where标签,自动将第一个and替换为where-->
    <!--多条件查询-->
    <select id="queryAll" parameterType="cn.cxm.mapper.query.EmployeeQuery" resultType="cn.cxm.mapper.domain.Employee">
        SELECT * FROM employee
        <where>
            <if test="name!=null and name!=''">
                AND name LIKE CONCAT("%",#{name},"%")
            </if>
            <if test="minAge!=null">
                AND age>=#{minAge}
            </if>
            <if test="maxAge!=null">
                AND <![CDATA[ age<=#{maxAge}]]>
            </if>
        </where>
    </select>

    <!--查询总条数-->
    <select id="count" parameterType="cn.cxm.mapper.query.EmployeeQuery" resultType="long">
        SELECT count(id) FROM employee
            <where>
                <if test="name!=null and name!=''">
                    AND name LIKE CONCAT("%",#{name},"%")
                </if>
                <if test="minAge!=null">
                    AND age>=#{minAge}
                </if>
                <if test="maxAge!=null">
                    AND <![CDATA[ age<=#{maxAge}]]>
                </if>
            </where>
    </select>

   

代码片段

<select id="findByQuery" parameterType="employeeQuery" resultType="employee">
        select * from employee <include refid="whereSql" />
</select>

<!--准备代码片断-->
<sql id="whereSql">
    <where>
        <if test="name!=null and name!=''">
            and name like concat("%",#{name},"%")
        </if>
        <if test="minAge!=null">
            and age >= #{minAge}
        </if>
        <if test="maxAge!=null">
            <![CDATA[ and age<=#{maxAge} ]]>
        </if>
    </where>
</sql>

批量删除,添加,动态修改

首先知道sql delete from 表名 where id in (?,?,…)
collection="":代表你要循环的是什么? array/list
如果传过来的是数据,写array(集合就写list)
item:循环的每一个数据
open:拼接字符串以什么开始
close:拼接字符串以什么结尾
separator:拼接的时候每个值使用,隔开
index:遍历的下标

动态修改

 <!--动态修改,当使用动态修改,只修改其中的一条数据,同一id的其他数据不会改变-->
    <update id="update" parameterType="cn.cxm.mapper.domain.Employee">
        UPDATE employee
        <set>
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="age!=null">
            age=#{age},
            </if>
        </set>
        WHERE id=#{id}
    </update>

批量删除

<!--批量删除,删除一定范围,使用in( ,)-->
    <delete id="batchDelete" parameterType="list">
        DELETE FROM employee WHERE id in
        <foreach collection="list" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

批量添加

<!--
    添加多条数据
    使用foreach标签,collection:遍历的集合,item:集合的每一个元素
    separator:分离符
    -->
    <insert id="batchSave" parameterType="list">
        INSERT INTO employee (name,age) VALUES
        <foreach collection="list" item="emp" separator=",">
            (#{emp.name},#{emp.age})
        </foreach>
    </insert>

多对一

准备两张表product、productdir,两个domain,两个mapper.xml
查询(嵌套结果:一条SQL,嵌套查询:多条SQL)

准备domain

product

 private Long id;
  private String name;
//  private Long dirId;
  private Double salePrice;
  private String supplier;
  private String brand;
  private Double cutoff;
  private Double costPrice;
  private Productdir productdir;
  //... getter,setter与toString

productdir

private Long id;
  private String name;
    //... getter,setter与toString

嵌套结果

查询的sql要关连多张表(一定要取别名,不然有些名称会产生冲突)
当我们使用了association 后默认的映射失败,需要自己手动完成映射
<?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="cn.cxm.many2one.mapper.ProductMapper">
    <!--手动完成映射,id为我们取的名字,type为我们映射的类型-->
    <resultMap id="ProductMap" type="cn.cxm.many2one.domain.Product">
        <id property="id" column="id"/>
        <result property="name" column="productName"/>
        <result property="salePrice" column="salePrice"/>
        <result property="supplier" column="supplier"/>
        <result property="brand" column="brand"/>
        <result property="cutoff" column="cutoff"/>
        <result property="costPrice" column="costPrice"/>

        <!--association:不管是多对一还是一对多都使用它,代表要关联一个对象,当你使用这个标签的时候,
        自动映射就会失效,property="productdir" :属性名称,javaType=":属性的类型-->
        <association property="productdir" javaType="cn.cxm.many2one.domain.Productdir">
            <id property="id" column="did"/>
            <result property="name" column="dname"/>
        </association>
    </resultMap>
    <!--嵌套结果-->
    <!--如果有字段名或者类型对应不上,这个时候我们需要手动映射
    当在查询中出现相同到的名称的字段的时候,为了区分,我们这个时候就要为它取别名-->
    <select id="findAll" resultMap="ProductMap">
        SELECT p.*,d.id did,d.name dname FROM product p
        JOIN productdir d on d.id=p.dir_id
    </select>
</mapper>

嵌套查询

会产生n+1条sql
需要去找到对应的那条sql并且执行
保证MyBatis能找到这两个xml

ProductdirMapper.xml

<?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="cn.cxm.many2one.mapper.ProductdirMapper">
    <select id="findOne" parameterType="long" resultType="cn.cxm.many2one.domain.Productdir">
        SELECT* FROM productdir WHERE id=#{id}
    </select>
</mapper>

Product.xml

<?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="cn.cxm.many2one.mapper.ProductMapper">
    <resultMap id="ProductMap" type="cn.cxm.many2one.domain.Product">
        <id property="id" column="id"/>
        <result property="name" column="productName"/>
        <result property="salePrice" column="salePrice"/>
        <result property="supplier" column="supplier"/>
        <result property="brand" column="brand"/>
        <result property="cutoff" column="cutoff"/>
        <result property="costPrice" column="costPrice"/>
        <association property="productdir" javaType="cn.cxm.many2one.domain.Productdir"
         column="dir_id" select="cn.cxm.many2one.mapper.ProductdirMapper.findOne"
        >
        </association>
    </resultMap>
    <!--嵌套查询-->
    <select id="findAll" resultMap="ProductMap">
        SELECT * FROM product p
    </select>
</mapper>

野方法

<?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="cn.cxm.many2one.mapper.ProductMapper">
    <resultMap id="ProductMap" type="cn.cxm.many2one.domain.Product">
        <!--野方法,直接设置值-->
        <result property="productdir.id" column="did" />
        <result property="productdir.name" column="dname" />
    </resultMap>
    <!--野方法-->
    <select id="findAll" resultMap="ProductMap">
        SELECT p.*,d.id did,d.name dname FROM product p
        JOIN productdir d on d.id=p.dir_id
    </select>
</mapper>

一对多

Product

private Long id;
  private String name;
//  private Long dirId;
  private Double salePrice;
  private String supplier;
  private String brand;
  private Double cutoff;
  private Double costPrice;

Productdir

 private Long id;
  private String name;

  private List<Product> product=new ArrayList<>();

嵌套结果

<?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="cn.cxm.one2many.mapper.ProductdirMapper">
    <!--手动完成映射,id为我们取的名字,type为我们映射的类型-->
    <resultMap id="ProductdirMap" type="cn.cxm.one2many.domain.Productdir">
        <id property="id" column="did"/>
        <result property="name" column="dname"/>
        <!--association:不管是多对一还是一对多都使用它,代表要关联一个对象,当你使用这个标签的时候,
        自动映射就会失效,property="productdir" :属性名称,javaType=":属性的类型-->
        <collection property="product" ofType="cn.cxm.one2many.domain.Product">

            <id property="id" column="pid"/>
            <result property="name" column="pname"/>
            <result property="salePrice" column="psalePrice"/>
            <result property="supplier" column="psupplier"/>
            <result property="brand" column="pbrand"/>
            <result property="cutoff" column="pcutoff"/>
            <result property="costPrice" column="pcostPrice"/>
        </collection>
    </resultMap>
    <!--嵌套结果-->
    <!--如果有字段名或者类型对应不上,这个时候我们需要手动映射
    当在查询中出现相同到的名称的字段的时候,为了区分,我们这个时候就要为它取别名-->
    <select id="findAll" resultMap="ProductdirMap">
        SELECT d.id did,d.name dname,p.id pid,p.ProductName pname,p.salePrice psalePrice,
        p.supplier psupplier,p.brand pbrand ,p.cutoff pcutoff,p.costPrice pcostPrice FROM productdir d
        LEFT JOIN product p on d.id=p.dir_id
    </select>
</mapper>

嵌套查询

productMapper

<?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="cn.cxm.one2many.mapper.ProductMapper">
    <select id="findBydeptId" parameterType="long" resultType="cn.cxm.one2many.domain.Product">
        SELECT * FROM product WHERE dir_id=#{id}
    </select>
</mapper>

productdirMapper

<?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="cn.cxm.one2many.mapper.ProductdirMapper">
    <!--手动完成映射,id为我们取的名字,type为我们映射的类型-->
    <resultMap id="ProductdirMap" type="cn.cxm.one2many.domain.Productdir">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!--association:不管是多对一还是一对多都使用它,代表要关联一个对象,当你使用这个标签的时候,
        自动映射就会失效,property="productdir" :属性名称,javaType=":属性的类型-->
        <collection property="product" ofType="cn.cxm.one2many.domain.Product"
        column="id" select="cn.cxm.one2many.mapper.ProductMapper.findBydeptId">
        </collection>
    </resultMap>
    <!--嵌套结果-->
    <!--如果有字段名或者类型对应不上,这个时候我们需要手动映射
    当在查询中出现相同到的名称的字段的时候,为了区分,我们这个时候就要为它取别名-->
    <select id="findAll" resultMap="ProductdirMap">
        SELECT * FROM productdir p
    </select>
</mapper>

缓存

自带一级级联
二级缓存需要加上标签 <cache />
二级缓存的对象必需是序列化对象 .. implements Serializable
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值