当前位置: 首页 > news >正文

【Java】关于mybatis动态拼接SQL实现动态查询时遇到的一些问题

一.首先是这些语句要写在哪里的问题

在 MyBatis 中,动态 SQL 语句主要有两种存放位置:XML 映射文件Mapper 接口中的注解。绝大多数情况下,尤其是对于复杂的动态 SQL,推荐使用 XML 文件来编写,这样能使 SQL 与 Java 代码分离,结构更清晰。

下面这个表格能帮你快速了解这两种方式的核心区别。

特性对比XML 映射文件Mapper 接口注解
适用场景复杂的、多条件的动态SQL(如包含多个 <if>, <foreach>, <choose>等标签)简单的、固定的SQL语句
可读性/维护性SQL 与 Java 代码分离,结构清晰,便于维护和审查较长或复杂的 SQLSQL 直接嵌入在 Java 代码中,若 SQL 较长会使方法体臃肿,可读性降低
灵活性非常高,支持所有动态 SQL 标签,能灵活拼接复杂 SQL灵活性较低,处理复杂动态 SQL 比较困难
配置要求需确保文件路径在 mybatis.mapper-locations配置的扫描路径下无需额外配置文件,但需在接口上使用 @Mapper或在启动类使用 @MapperScan
💡 XML 映射文件详解

这是组织和管理动态 SQL 最常用、最标准的方式。

  • 文件位置与命名:通常,XML 文件应放在项目的 src/main/resources目录下。为了更好的管理,建议其路径与对应的 Mapper 接口的包名保持一致。例如,如果你的 Mapper 接口全限定名为 com.example.mapper.UserMapper,那么对应的 XML 文件应放在 src/main/resources/com/example/mapper目录下,并命名为 UserMapper.xml

  • 基本文件结构:一个标准的 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="com.example.mapper.UserMapper"> 
    <!-- 在这里编写你的所有SQL语句,如 <select>, <insert>, <update>, <delete> 等 -->
    </mapper>
    

    关键点<mapper>标签的 namespace属性必须与对应的 Mapper 接口的全限定名完全相同。

  • 核心配置:为了让 MyBatis 找到这些 XML 文件,你需要在 application.propertiesapplication.yml中进行配置,但这通常只在 XML 文件与 Mapper 接口不在同一路径下时才需要。如果路径一致,Spring Boot 和 MyBatis 的默认配置通常就能自动识别。

  • application.properties

  • mybatis.mapper-locations=classpath:com/example/mapper/*.xml
    

    application.yml

    mybatis:mapper-locations: classpath:com/example/mapper/*.xml
    

对于非常简单的 SQL 语句,你也可以选择将动态 SQL 直接写在 Mapper 接口的方法上,使用 @Select, @Insert等注解,并配合 <script>标签。但正如前面表格所比,当 SQL 逻辑变得复杂时,这种方式会使得 Java 代码变得难以阅读和维护。

💎 建议
  • 优先选择 XML 文件:对于绝大多数涉及动态 SQL 的场景,强烈建议使用 XML 映射文件。这是 MyBatis 框架设计的最佳实践,能够带来更好的可读性、可维护性和灵活性。
  • 确保配置正确:使用 XML 方式时,请务必检查 namespace是否正确以及 XML 文件是否被正确放置在类路径下,这是成功运行的关键。
  • 简单场景考虑注解:只有当 SQL 极其简单且基本固定不变时,才考虑使用注解方式。
二.然后是关于直接使用WHERE并在每个条件前加AND,当首个条件为空时,SQL会因多出AND而报语法错误的问题
场景实现思路潜在问题解决方案
手动拼接 WHERE在 SQL 中直接写 WHERE,然后在每个 <if>条件前加 AND当第一个条件不成立时,WHERE后会紧跟一个多余的 AND,导致 SQL 语法错误。使用 MyBatis 的 <where>标签替代手写的 WHERE关键字。
使用 <where>标签<where>标签包裹动态条件,无需手动写 WHERE自动解决: 1. 有条件时,自动添加 WHERE。 2. 无条件时,自动忽略 WHERE。 3. 自动去除紧跟其后首个条件前多余的 ANDOR遵循 MyBatis 动态 SQL 的最佳实践。
💻 问题代码示例
<!-- ❌ 有风险的写法:手动拼接 WHERE -->
<select id="searchBlogs" parameterType="map" resultType="Blog">SELECT * FROM blogWHERE<if test="state != null">state = #{state}</if><if test="title != null">AND title LIKE CONCAT('%', #{title}, '%')</if>
</select>

假设调用时只传了 title参数,没有传 state参数。那么 MyBatis 动态生成的 SQL 会是这样:

SELECT * FROM blog WHERE AND title LIKE '%关键字%'

这条 SQL 在 WHERE后面直接跟了 AND,是错误的语法,数据库执行时会报错。

✅ 解决方案:使用 <where>标签

<where>标签的智能之处在于,它能自动处理 WHERE关键字以及条件前的 ANDOR

<!-- ✅ 正确的写法:使用 <where> 标签 -->
<select id="searchBlogs" parameterType="map" resultType="Blog">SELECT * FROM blog<where><if test="state != null">AND state = #{state}</if><if test="title != null">AND title LIKE CONCAT('%', #{title}, '%')</if></where>
</select>

现在,同样只传入 title参数,<where>标签会智能地:

  1. 发现有条件需要拼接,于是自动添加 WHERE关键字。
  2. 发现第一个有效的条件(title条件)前面有一个 AND,于是自动将其去除

最终生成的标准 SQL 如下:

SELECT * FROM blog WHERE title LIKE '%关键字%'

如果所有条件都为空,<where>标签感知到内部没有任何内容,则根本不会生成 WHERE子句,SQL 变为 SELECT * FROM blog,查询整张表,这也是符合逻辑的。

🛠️ 相关标签:<set><trim>

理解了 <where>,再了解两个功能相似的标签会更有帮助:

  1. <set>标签:用于 UPDATE语句,解决动态更新字段时末尾可能多出逗号的问题。<update id="updateBlogSelective"> UPDATE blog <set> <if test="title != null">title = #{title},</if> <if test="content != null">content = #{content},</if> </set> WHERE id = #{id} </update>
  2. <trim>标签:一个更底层的万能工具,可以自定义要添加/去除的前缀和后缀。事实上,<where><set>标签在 MyBatis 底层都可以用 <trim>来实现。
  3. <where>等价于:`…``
  4. ``等价于:…`
三.最后附带MyBatis 提供的多个常用的智能标签

。MyBatis 提供了多个智能标签来帮助我们在构建动态 SQL 时避免语法错误。除了你已经熟悉的 <where> 标签,<set><trim> 标签在处理更新操作和需要更精细控制的场景中尤其有用,<foreach> 标签则能优雅地处理集合遍历。下面的表格总结了这些标签的核心功能。

标签名称主要作用解决的典型语法错误经典应用场景
<where>自动插入 WHERE 关键字,并去除子句开头多余的 ANDOR避免 WHERE 后直接跟 AND/OR 导致的错误。多条件动态查询。
<set>自动插入 SET 关键字,并去除更新字段末尾多余的逗号。避免 UPDATE 语句中字段列表末尾多余的逗号。动态更新部分字段。
<trim>一个功能更强大的标签,允许自定义要添加/去除的前缀和后缀。可替代 <where><set>,也能处理更复杂的拼接逻辑。需要高度定制 SQL 片段格式的场景。
<foreach>遍历集合(如 List、数组),自动处理 IN 条件或批量值的分隔符和括号。避免手动拼接 IN 语句或批量操作时的格式错误。按ID列表查询、批量插入/更新/删除。
💡 各标签的智能之处

下面我们通过具体例子来看看这些标签如何避免SQL语法错误。

🔧 <set> 标签:更新语句的“逗号杀手”

在动态更新语句中,如果只使用 <if> 标签,当最后一个更新的字段条件不成立时,SQL 语句末尾可能会留下一个多余的逗号,导致语法错误。 <set> 标签可以智能地解决这个问题。

• 问题示例:如果不使用 <set> 标签,动态生成的 SQL 可能如下,注意 name 字段后的逗号是多余的:

```sql
UPDATE users SET name=?, age=?, WHERE id=?
```

• 解决方案:使用 <set> 标签包裹更新字段。

```xml
<update id="updateUser" parameterType="User">UPDATE users<set><if test="name != null">name = #{name},</if><if test="age != null">age = #{age},</if><if test="email != null">email = #{email},</if></set>WHERE id = #{id}
</update>
```
`<set>` 标签会智能地:
1.  只在至少有一个更新条件成立时插入 `SET` 关键字。
2.  自动去除字段列表末尾多余的逗号。
🎨 <trim> 标签:高度自定义的“万能工具”

<trim> 标签功能非常灵活,它可以实现 <where><set> 标签的效果,并能应对更复杂的场景。 它通过四个属性来实现精确控制:
prefix:在内容前添加指定的前缀(如 WHERESET)。

suffix:在内容后添加指定的后缀。

prefixOverrides:去除内容开头指定的字符(如 ANDOR)。

suffixOverrides:去除内容末尾指定的字符(如逗号 ,)。

• 使用 <trim> 实现 <where> 的功能:

```xml
<trim prefix="WHERE" prefixOverrides="AND |OR "><!-- 动态条件 -->
</trim>
```

• 使用 <trim> 实现 <set> 的功能:

```xml
<trim prefix="SET" suffixOverrides=","><!-- 动态更新字段 -->
</trim>
```
🔁 <foreach> 标签:优雅遍历集合

<foreach> 标签主要用于遍历集合,构建 IN 条件语句或批量操作语句,它能自动处理括号和元素之间的分隔符,避免手动拼接的错误。

• 应用示例:根据ID列表查询用户

```xml
<select id="selectUsersByIds" resultType="User">SELECT * FROM usersWHERE id IN<foreach collection="list" item="id" open="(" close=")" separator=",">#{id}</foreach>
</select>
```
假设传入的ID列表是 `(1, 2, 3)`,`<foreach>` 会生成 `WHERE id IN (1,2,3)`。`open` 指定了以什么开始(这里是左括号),`close` 指定了以什么结束(这里是右括号),`separator` 指定了元素之间的分隔符(这里是逗号)。
http://www.dtcms.com/a/561788.html

相关文章:

  • 做电影网站会违法吗网站模块怎么恢复
  • 网站程上传服务商类型是什么意思
  • 3.基础--数据模型
  • 设计logo网站生成器个人电脑做网站服务器网站
  • 49.渗透-Yakit-基础模块应用(爆破与未授权检测)
  • Taro 开发快速入门手册
  • html5网络公司网站模板wordpress 左右翻页
  • Python GUI 编程(Tkinter)
  • 外贸商业网站建设重庆专业的网站建设公司
  • 做怎么样的网站好wordpress 技术类主题
  • Java 大视界 -- Java 大数据在智能政务公共资源交易数据分析与监管中的应用
  • 雅思口语主题
  • 江门网站江苏建设厅长
  • 多模态数据湖对接 AI 训练的技术方案
  • 计算机组成原理核心知识点梳理
  • 天津手机网站建设制作省级别网站建设方案
  • 家政服务网站建设方案宁波网站建设就业方向
  • 网站程序的设计费用网站添加wordpress博客
  • 第三方接口请求
  • 个人网站做装修可以吗网页游戏网站排名
  • C语言字符串及其函数
  • 网站设计公司-信科网络有什么免费建网站
  • Nestjs框架: 微服务容器化部署与网络通信解决方案
  • 北京网络网站建设公司手机必备app
  • 苏州网站建设公司电话网站无法连接mysql
  • 五.docker环境搭建实例
  • 网工错题笔记
  • 龙之向导外贸网站集团公司手机站网站
  • 电商网站竞价推广策略财务网站建设
  • spring boot 启动过程