mybatis(3)-动态sql

目录

动态sql

1. if

2.  trim、where、set

1. where

2. trim

3. set

4. foreach

5. choose

6. 其他标签,script、 bind、selectKey

script

bind

selectKey获取主键


动态sql

 

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,

eg:

拼接时要确保不能忘记添加必要的空格

注意去掉列表最后一个列名的逗号。

利用动态 SQL,可以彻底摆脱这种痛苦。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

 

1. if

if判断语句,如果满足条件,则可以将该条件拼入,否则不拼入该条件。

    <select id="getStudent" resultType="com.hww.bean.Student">
        select * from student
        where
          <if test="student_id!=null">student_id=#{studentId}</if>
          <if test="name!=null">and name=#{name}</if>
    </select>

但是如果所有的条件都不满足的话。sql语句就会变成     select * from student where  ,这样执行是会报错的。

如果第条件不满足第二个条件满足,就会变成 select * from student where and name='xxx' ,这语句更是错误。

那么我们进行修改升级

    <select id="getStudent" resultType="com.hww.bean.Student">
        select * from student
        where 1=1 
          <if test="student_id!=null">and student_id=#{studentId}</if>
          <if test="name!=null">and name=#{name}</if>
    </select>

这样条件不满足时 sql语句变为select * from student where 1=1。这样就需要每次都写1=1,这样不友好。

那么我们怎么做呢。

2.  trim、where、set

1. where

对与以上问题的改进where标签,where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

<where>能实现两个功能

  •  当有条件满足是才会加 where
  • 如果条件的开头是and 或者or时,能够默认去掉
    <select id="getStudent" resultType="com.hww.bean.Student">
        select * from student
        <where>
          <if test="student_id!=null">and student_id=#{studentId}</if>
          <if test="name!=null">and name=#{name}</if>
        <where>
    </select>

2. trim

当然也可用trim标签实现where的功能

怎么实现的呢

在语句开头,将prefixOverrides的值会被去掉。并且首行加入前缀prefix的值 下面的例子就是说

如果开头是以 and+空格 或者 or+空格开头就会去掉并且首行加入前缀where。这个也可以满足

注意这里的prefixOverrides="and |or ",后面有个空格的。

    <select id="getStudent" resultType="com.hww.bean.Student">
        select * from student
        <trim prefix="where" prefixOverrides="and |or ">
            <if test="student_id!=null">and student_id=#{studentId}</if>
            <if test="name!=null">and name=#{name}</if>
        </trim>
    </select>

3. set

该标签一般用在update语句中

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

    <update id="updStudent">
        update student
        <set>
            <if test="studentId!=null">student_id=#{studentId},</if>
            <if test="name!=null">name=#{name}</if>
        </set>
        <where>
          <if test="studentId!=null">
              student_id = #{studentId}
          </if>
        </where>
    </update>

同理也可用trim实现

    <update id="updStudent">
        update student
        <trim prefix="set" suffixOverrides=",">
            <if test="studentId!=null">student_id=#{studentId},</if>
            <if test="name!=null">name=#{name}</if>
        </trim>
        <trim prefix="where" prefixOverrides="and |or ">
          <if test="studentId!=null">
              student_id = #{studentId}
          </if>
        </trim>
    </update>

 

4. foreach

<foreach collection="list" item="itme" open="(" close=")" separator=",">

collection 集合

item 表示每一个元素,如果集合中放的是对象,则item只得是每个对象

open 和 close 表示以什么开始,以什么结束

separator,表示循环的每个元素之间的分割符。

    <insert id="addStudentAll">
        insert into student (name)values
          <foreach collection="list" item="item" open="" close="" separator=",">
              (#{item.name})
          </foreach>
    </insert>
    
    <select id="selectStuAll">
        select * from student 
        <where>
            student_id in 
            <foreach collection="list" item="itme" open="(" close=")" separator=",">
                #{item}
            </foreach>
        </where>
    </select>

5. choose

等同于switch case

选择其中的一个执行。

<select id="getStudentTwo" resultType="com.hww.bean.Student">
        select * from student where
        <choose>
            <when test="studentId!=null">student_id=#{studentId}</when>
            <when test="name!=null">name=#{name}</when>
            <otherwise>1=1</otherwise>
        </choose>
    </select>

 

6. 其他标签,script、 bind、selectKey

 

  • script

要在带注解的映射器接口类中使用动态 SQL,可以使用 script 元素。比如:

@Update(数组)

    @Update({"<script>",
            "update student",
            "<set>",
            "<if test='studentId!=null'>student_id=#{studentId},</if>",
            "<if test='name!=null'>name=#{name},</if>",
            "</set>",
            "where student_id=#{studentId}",
            "</script>"})
    public void updStudentOne(Student stu);
  • bind

bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。比如:

在使用模糊查询sql时,如果使用${}进行字符拼接,无法防止sql诸如问题,如果使用concat函数则只对mysql有效果,用Oracle则需要用连接符||,这样在数据库变的时候需要修改,不利于移植。mybatis提供元素<bind>很好能解决这个问题。

    <!--bind-->
    <select id="getBindStu" resultType="com.hww.bean.Student">
        <bind name="aaa" value= "_parameter.getStudentId()" />
      select * from student where student_id=#{aaa}
    </select>

其中bind元素, <bind name="aaa" value= "_parameter.getStudentId()" />。就是将value值绑定到变量aaa上了,而value=_parameter.getStudentId()。这里应该是 参数调用参数的方法。参数是Student对象,调用student.getStudentId()获取到值,赋值给变量aaa,

然后在查询时引用aaa变量。

    @Test
    public void testGetBindStu(){
        TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
        Student student = new Student(1,1,"mm");
        Student bindStu = mapper.getBindStu(student);
        System.out.println(bindStu);
        sqlSession.close();
    }
  • selectKey获取主键

在insert数据是,如果我们要获取一个主键怎么获取,

<selectKey keyProperty="id" resultType="int" order="BEFORE">

keyProperty: 表示主键的属性,与数据库主键字段对应

resultType: 返回类型,类型为int

order:before,after 表示在insert语句之前执行还是之后执行。对于没有自增主键的数据库来说,就需要再之前获取。比如oracle

<insert id="insert">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    <if test="_databaseId == 'oracle'">
      select seq_users.nextval from dual
    </if>
    <if test="_databaseId == 'db2'">
      select nextval for seq_users from sysibm.sysdummy1"
    </if>
  </selectKey>
  insert into users values (#{id}, #{name})
</insert>

如果配置了 databaseIdProvider,你就可以在动态代码中使用名为 “_databaseId” 的变量来为不同的数据库构建特定的语句

databaseIdProvider在mybatis配置中配置。

 

 

Mybatis-plus是在Mybatis基础上进行封装的一个框架,它简化了平时开发过程中对常用接口的调用,可以省去一些繁琐的操作。然而,对于一些更为复杂的查询Mybatis-plus可能无法满足需求,此时就需要我们自定义SQL语句来实现。通过在入口类的MybatisSqlSessionFactoryBuilder#build方法中注入mybatis-plus自定义的动态配置xml文件,可以实现自定义SQL语句和动态SQL的功能。具体的实现步骤如下: 1. 在应用启动时,在入口类的MybatisSqlSessionFactoryBuilder#build方法中将mybatis-plus的自定义动态配置xml文件注入到Mybatis中。 2. 在自定义的动态配置xml文件中,可以使用各种Mybatis-plus提供的方法来实现动态SQL的功能,比如IF标签、CHOOSE标签、FOREACH标签等。 3. 在自定义SQL语句中,可以结合Mybatis-plus的Wrapper类来实现条件查询,例如使用LambdaQueryWrapper来构建查询条件。 总结起来,Mybatis-plus提供了简化开发的接口,但对于一些更为复杂的查询,仍然需要我们自定义SQL语句和动态SQL来实现。通过注入自定义的动态配置xml文件,并结合Mybatis-plus提供的方法和Wrapper类,可以实现更加灵活和高效的数据查询。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [mybatis-plus/mybatis 自定义 sql 语句、动态 sql](https://blog.csdn.net/CREATE_17/article/details/109117091)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Mybatis Plus实现动态SQL语句的原理,你知道吗?](https://blog.csdn.net/weixin_38405253/article/details/119880820)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值