三、Mybatis第三节

本文介绍了MyBatis中动态SQL的使用,包括sql片段、set标签、foreach标签在更新、查询和删除操作中的应用。同时,讲解了如何处理映射文件中的特殊字符,提供了转义和CDATA的方式。最后,提到了模糊查询和联表查询的实现方法,包括使用concat函数和like操作符,以及通过resultMap进行联表查询。

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

一、动态sql

1.1 sql片段

        在书写sql语句的查询时,不推荐大家用 * 号,建议大家把想要查询出来的列都写出。具体的写法如下:(1)写sql标签 (2)在sql语句中引入sql片段

1.2 set标签

        set标签多配合if标签一起使用,一般都是用在修改语句。例子:如果传递的参数值为null,不修改该列的值。

set标签可以帮我们生成sql内的关键字---set,并且可以动态的帮我们去除最后一个逗号。代码如下:

        

测试代码如下:我们传的参数为一个student实体类,里面的属性有name,age,cid和一个ACalss(自定义的)类的aclass,我们只需要关系我们要用到的name,age和cid即可。

    @Test
    public void testUpdateBySet() throws Exception{
        SqlSession session = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis.xml")).openSession();
        StudentDao studentDao = session.getMapper(StudentDao.class);
        Student student = new Student(1,"lrs",45,2,null);
        //Student student1 = new Student(2,"",18,null,null);
        int i = studentDao.updateBySet(student);
        System.out.println(i);
        session.commit();
        session.close();
    }

我们需要修改的值为name,age,cid,这些都不为空, 那么动态sql语句就应该变成:

 可以发现,set标签会自动帮我们去除最后cid处的逗号。

1.3 foreach标签

        循环标签,可以帮助我们处理一些动态的批量任务,例如批量添加,批量查询,批量删除等等。我们可以传入一个数组或者一个list集合,然后通过foreach标签将集合内的条件一个一个的放入我们的sql语句从而实现动态的批量处理效果。

foreach标签内属性:

  • collection:类型  如果你使用的为数组array  如果你使用的为集合 那么就用list
  • item:数组中每个元素赋值的变量名
  •  open: 以谁开始
  • close:以谁结束
  • separator:分割符

        用到的数据库的表如图。下面给大家列举三个例子:

(1)根据id批量查询学生信息

        StudentDao:

        StudentMapper:

    <resultMap id="stuMap" type="com.lrs.entity.Student">
        <id column="stu_id" property="id"/>
        <result column="stu_name" property="name"/>
        <result column="stu_age" property="age"/>
    </resultMap>
    <sql id="stu">
        stu_id,stu_name,stu_age,cid
    </sql>
    <select id="selectByFor" resultMap="stuMap">
        select
        <include refid="stu"/>
        from student where stu_id in
        <foreach collection="array" item="forEachIds" separator="," open="(" close=")">
            #{forEachIds}
        </foreach>

    </select>

(2)根据id批量删除

        StudentDao:

        StudentMapper:

    <delete id="deleteBuFor">
        delete from student where stu_id in
        <foreach collection="array" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>

(3)批量添加学生信息

        这里我们传入的参数可以换成集合类型------List<Student>集合。集合里面装的都是Student对象类型的数据。这样才能将要添加的学生的信息传入到sql中。

        StudentDao:

        StudentMapper:注意,我们要想调用list集合内的Student对象的属性,调用的写法应该为“Xxx(item名称).xxx(属性名)”。同样自定义对象类型的数组也应该这样调用属性。

    <insert id="insertByFor">
        insert into student values
        <foreach collection="list" item="stu" separator=",">
            (null,#{stu.name},#{stu.age},#{stu.cid})
        </foreach>
    </insert>

二、映射文件特殊字符的处理

        在Mapper中写我们的sql语句中,会遇到一些特殊的字符,他会与我们的sql代码会产生冲突,例如我们sql中写这样的语句:

        可以看到我们的小于号,就是一种特殊字符。那么我们该如何处理这种问题?

        有两种方法可以解决。

第一种:使用转义符。java中有这些特殊字符的转义符。

第二种:用   <![CDATA[sql语句]]> 方法 注意这种方法不能括住我们的标签(例如include标签),我们可以在需要用到的地方使用这个方法,没必要整个sql语句都套入在内。

三、模糊查询

        模糊查询的sql语句:

select * from 表名 where 列名 like '%a%'

         有两种方法可以实现这种拼接。

(1)使用字符串函数 完成拼接 -----concat(这属于sql基础的知识点)

    <select id="selectByLike" resultMap="stuMap">
        select <include refid="stu"/> from student where stu_name like concat('%',#{name},'%') 
    </select>

(2) 使用${ } 代替。 这种方式实际上是字符串的拼接,他并不能防止sql注入问题,而我们之前用的#{ }就相当于预编译,可以防止sql注入问题。所有这种方式不推荐使用,所谓防君子不防小人。

    <select id="selectByLike" resultMap="stuMap">
        select <include refid="stu"/> from student where stu_name like '%${name}%'
    </select>

四、联表查询

        例子:根据id查询学生信息并包括该学生所在的班级信息。

        需要用的表:我们需要从多的一方来查询一的一方。这里学生表就相当于多的一方,班级表就相当于1的一方。

        sql语句:

select * from tb_stu s join tb_class c on s.class_id=c.cid where stu_id= xxx

 实现方式一:

        首先在我们的Student实体类种(相当于多的一方)加入我们AClass类型(一的一方)的属性

package com.lrs.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @作者:刘壬杉
 * @创建时间 2022/6/3
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private Integer cid;
    private AClass aClass;  //AClass类型的属性。
}

StudentDao:

 StudentMapper: 重点:resultMap标签内的association标签 :表示 一 的一方。property:表示属性名(就是我们实体类种的aclass属性)。javaType:表示该属性名对应的数据类型。

    <resultMap id="all" type="com.lrs.entity.Student">
        <id column="stu_id" property="id"/>
        <result column="stu_name" property="name"/>
        <result column="stu_age" property="age"/>
        <result column="c_id" property="cid"/>
        <association property="aClass" javaType="com.lrs.entity.AClass">
            <id column="cid" property="cid"/>
            <result column="cname" property="cname"/>
        </association>
    </resultMap>
    <sql id="allClass">
        stu_id,stu_name,stu_age,s.cid c_id,c.cid,cname
    </sql>
    <select id="selectClassById" resultMap="all">
        select <include refid="allClass"/> from student s join class c on s.cid = c.cid where stu_id=#{id}
    </select>

实现方式二:

       map封装(不推荐这种方式)。用这种方式封装我们查询到的数据,就不需要改动我们的实体类,也不用关心其属性内的映射关系。

        StudentDao:

         StudentMapper:

    <select id="selectClassById2" resultType="java.util.Map">
        select <include refid="allClass"/> from student s join class c on s.cid = c.cid where stu_id=#{id}
    </select>

        需要避免的问题:两个表的列名应该尽量避免相同,如果相同,需要起别名来区别。resultMap中的标签内的column属性应该与你起了别名后的列名相同。Map本身也是无序不重复的,我们的属性名也就是map中的key值也需要保证不能相同。

       体会:使用mybatis我们需要做的事情就是处理好查询到的结果与返回值(一般是你得实体类或实体类组成的集合)的属性相对应(resultMap标签)。其他的内容与我们学习JDBC+Dao整合时大致相同。所以难点就在于将返回的内容处理好,其他的一些包括sql语句标签和动态sql标签都是帮助我们书写sql语句的,基础的sql部分的知识点需要掌握。框架的好处就是帮我们简化流程,不要把他想的很复杂。

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值