mybatis @Select注解中如何拼写动态sql

本文介绍如何在MyBatis中实现分页查询,并通过动态SQL进行条件过滤。展示了如何利用@Select注解结合script标签实现根据参数动态生成SQL语句,同时解决了参数类型不匹配导致的错误。

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

@Mapper
public interface DemandCommentMapper extends BaseMapper<DemandComment>{
    @Select("SELECT "
            + "a.id as 'id',a.create_date as 'createDate',a.content as 'content',"
            + "a.parent_id as 'parentId',a.first_comment_id as 'firstCommentId',"
            + "b.id as 'fromUser.id',b.realname as 'fromUser.realname',b.avatar as 'fromUser.avatar',"
            + "c.id as 'toUser.id',c.realname as 'toUser.realname',c.avatar as 'toUser.avatar' "
            + "FROM t_demand_comment a "
            + "LEFT JOIN t_user b ON b.id = a.from_uid "
            + "LEFT JOIN t_user c ON c.id = a.to_uid "
            + "WHERE a.demand_id = #{demandId} "
            + "ORDER BY a.create_date ASC"
            + "LIMIT #{startNo},#{pageSize}")
    public List<DemandComment> listDemandComment(@Param("demandId") Long demandId, 
                             @Param("startNo") Integer pageNo,
                             @Param("pageSize") Integer pageSize);

  这样整个语句是写死的,如果我想根据pageNo与pageSize是否为空来判断是否需要分页,该怎么做呢?

  如果使用xml来配置的话可以用

<when test='startNo!=null and pageSize != null '>
  LIMIT #{startNo},#{pageSize}
</when>

  如果是用@Select 这种该如何做呢?

  方法:用script标签包围,然后像xml语法一样书写

@Mapper
public interface DemandCommentMapper extends BaseMapper<DemandComment>{
    @Select("<script>"
            + "SELECT "
            + "a.id as 'id',a.create_date as 'createDate',a.content as 'content',"
            + "a.parent_id as 'parentId',a.first_comment_id as 'firstCommentId',"
            + "b.id as 'fromUser.id',b.realname as 'fromUser.realname',b.avatar as 'fromUser.avatar',"
            + "c.id as 'toUser.id',c.realname as 'toUser.realname',c.avatar as 'toUser.avatar' "
            + "FROM t_demand_comment a "
            + "LEFT JOIN t_user b ON b.id = a.from_uid "
            + "LEFT JOIN t_user c ON c.id = a.to_uid "
            + "WHERE a.demand_id = #{demandId} "
            + "ORDER BY a.create_date ASC "
            + "<if test='startNo!=null and pageSize != null '>"
            + "LIMIT #{startNo},#{pageSize}"
            + "</if>"
            + "</script>")
    public List<DemandComment> listDemandComment(@Param("demandId") Long demandId, 
                             @Param("startNo") Integer pageNo,
                             @Param("pageSize") Integer pageSize);

  项目实例

  @Select("<script>"
            +"select * from mi_taobao where 1=1"
            +"<if test='status != null'>"
            +"and status = #{status}"
            +"</if>"
            +"</script>")
    public List<Taobao> getTaobao(@Param("status") Integer status);

  在这里还碰到一个问题就是报错:Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'status' in 'class java.lang.Interger'

  出现原因:这里出现的问题是在DAO方法中定义的参数 与 实体中定义的属性不一致 导致的。

  解决方案:dao层加@Param("userId")注解即可(实例中就是加上@Param("status")

  public List<DictItem> selectKeyByUserId(@Param("userId") long userId);

 

<think>首先,用户的问题是关于MyBatis@Select注解中如何实现动态SQL查询。我需要基于系统级指令来构建回答。 系统级指令: 1. 所有行内数学表达式必须使用$...$格式。例如,$x^2$。 2. 独立公式必须使用$$...$$格式并单独成段。 3. LaTeX语法正确。 4. 使用中文回答。 5. 生成相关问题。 6. 回答中引用的段落末尾自然地添加引用标识,例如:[^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 - 参考站内引用:[^1], [^2], [^3]。 提供的引用: - [^1]: 关于MyBatis @Select注解模糊查询的两种方式。 - [^2]: 使用@Select注解动态SQL语句,包括if标签。 - [^3]: 当参数为空时不添加该参数的判断,模糊查询示例。 用户的问题:如何在MyBatis@Select注解中编写动态SQL查询。 我的回答需要: - 使用中文。 - 结构清晰,逐步解决问题。 - 包含行内数学表达式(如果适用),但由于主题是SQL,可能不直接涉及数学。但指令说所有行内数学表达式必须使用$...$,所以如果有数学部分,必须处理。但这里可能没有数学,所以或许不需要。 - 生成相关问题。 - 在引用段落末尾添加引用标识。 步骤: 1. **理解需求**:用户想了解如何在@Select注解中实现动态SQL查询。动态SQL允许根据条件构建SQL语句。 2. **参考引用**: - [^1]:模糊查询的两种方式,使用${}或concat。 - [^2]:使用<script>标签和if标签来实现动态SQL。 - [^3]:参数为空时不添加条件,包括模糊查询示例。 3. **结构回答**: - 介绍动态SQLMyBatis中的作用。 - 解释使用@Select注解实现动态SQL的方法。 - 提供示例代码。 - 讨论常见场景,如模糊查询、条件判断。 - 添加引用标识。 - 生成相关问题。 4. **处理数学表达式**:主题是编程,可能没有数学表达式。但指令说所有行内数学表达式必须使用$...$,所以如果有变量或简单的表达式,可以应用。例如,在解释SQL语法时,如果有类似表达式,用$...$包裹。但在这个上下文中,可能不必要。指令说“包括变量、不等式、方程等”,但SQL查询不是数学表达式。为了安全起见,我可以在解释参数时使用$...$,比如$name$表示变量名。 5. **生成相关问题**:在回答末尾,添加相关问题部分。 大纲回答: - **引言**:简要介绍MyBatis动态SQL@Select注解。 - **方法1:使用<script>标签**:解释如何用<script>包裹SQL,并使用if、choose等标签。 - 示例代码。 - 引用[^2]。 - **方法2:模糊查询示例**:展示模糊查询的实现。 - 使用concat函数或${}方式。 - 引用[^1]。 - **处理参数为空**:如何在参数为空时跳过条件。 - 示例代码。 - 引用[^3]。 - **总结**:最佳实践或注意事项。 - **相关问题**:生成3-5个相关问题。 确保LaTeX语法正确:如果没有数学,可能不需要。但指令说“所有行内数学表达式”,所以或许在描述变量时使用$name$。 例如:在SQL中,参数如$name$可以动态插入。 生成相关问题: 1. MyBatis动态SQL中如何防止SQL注入? 2. @Select注解与其他注解(如@Insert)的区别? 3. 如何优化MyBatis动态SQL的性能? 4. 模糊查询的替代方法? 5. MyBatis中如何处理多个条件? 引用添加:在引用段落末尾添加[^n]。例如,当提到模糊查询方式时,添加[^1]。 完整回答:</think>### MyBatis @Select 注解中实现动态 SQL 查询的方法 MyBatis 是一个优秀的持久层框架,支持在注解(如 `@Select`)中编写动态 SQL 查询,允许根据参数值动态构建 SQL 语句。这在处理条件查询、模糊匹配等场景时非常实用。下面我将逐步解释实现方法,并提供示例代码。实现动态 SQL 的核心是使用 MyBatis 的 OGNL 表达式和 XML 标签(如 `<if>`, `<choose>`),通过 `<script>` 标签包裹 SQL 语句来实现动态逻辑[^2]。 #### 步骤 1: 使用 `<script>` 标签包裹 SQL 在 `@Select` 注解中,用 `<script>` 标签包裹整个 SQL 语句,这允许在其中嵌入动态标签(如 `<if>`, `<when>`)。这些标签基于参数值决定是否添加特定 SQL 片段。 - **语法要点**: - 用 `<script>` 开始和结束。 - 使用 `<if test="条件">` 添加条件判断。 - 参数引用使用 `#{参数名}` 来防止 SQL 注入。 - 示例:查询用户表,当用户名参数 `$name$` 不为空时,添加模糊查询条件[^3]。 ```java @Select({ "<script>", "SELECT * FROM user", "WHERE 1=1", // 初始条件,确保后续 AND 语句有效 "<if test='name != null and name != \"\"'>", "AND name LIKE CONCAT('%', #{name}, '%')", // 使用 CONCAT 实现模糊查询 "</if>", "</script>" }) List<User> selectUsersByName(String name); // 参数 name 可为空 ``` - **说明**: - 如果 `$name$` 为空,SQL 会简化为 `SELECT * FROM user WHERE 1=1`,忽略模糊条件。 - `CONCAT('%', #{name}, '%')` 是安全的模糊查询方式,避免使用 `${}` 导致的注入风险[^1]。 - 引用:该方法支持动态添加条件,确保代码灵活[^2]。 #### 步骤 2: 实现模糊查询的两种方式 模糊查询是动态 SQL 的常见需求。MyBatis 提供两种主要方式,各有优缺点: - **方式 1: 使用 `CONCAT` 函数(推荐)** - 安全可靠,防止 SQL 注入。 - 语法:`LIKE CONCAT('%', #{param}, '%')`。 - 示例: ```java @Select({ "<script>", "SELECT * FROM product", "WHERE description LIKE CONCAT('%', #{keyword}, '%')", // 直接嵌入模糊逻辑 "</script>" }) List<Product> searchProducts(String keyword); ``` - 引用:这种方式在参数处理上更安全[^1]。 - **方式 2: 使用 `${}` 插值(不推荐)** - 简单但危险,易引发 SQL 注入。 - 语法:`LIKE '%${param}%'`。 - 示例: ```java @Select("SELECT * FROM user WHERE username LIKE '%${name}%'") // 直接拼接字符串 List<User> selectUsersByName(String name); ``` - **警告**:仅在内部可信参数时使用,否则应避免[^1]。 #### 步骤 3: 处理多条件动态查询 对于复杂场景(如多参数组合),使用 `<choose>`, `<when>`, `<otherwise>` 标签实现分支逻辑。 - **示例:多条件用户查询** - 需求:根据 `$name$`(模糊匹配)、`$age$`(精确匹配)和 `$status$`(可选状态)动态构建 SQL。 - 代码: ```java @Select({ "<script>", "SELECT * FROM user", "WHERE 1=1", "<if test='name != null and name != \"\"'>", "AND name LIKE CONCAT('%', #{name}, '%')", "</if>", "<if test='age != null'>", "AND age = #{age}", "</if>", "<choose>", "<when test='status != null'>", "AND status = #{status}", "</when>", "<otherwise>", "AND status = 'active'", // 默认值 "</otherwise>", "</choose>", "</script>" }) List<User> selectUsers(String name, Integer age, String status); ``` - **说明**: - `<if>` 用于非必要条件(如 `$name$` 或 `$age$` 为空时跳过)。 - `<choose>` 实现多分支,类似 switch-case 逻辑。 - 引用:此方法确保参数为空时自动忽略相关条件[^3]。 #### 最佳实践与注意事项 - **防止 SQL 注入**:优先使用 `#{}` 而非 `${}`,因为 `#{}` 会预编译参数,而 `${}` 直接拼接字符串[^1]。 - **性能优化**:避免过度动态化,复杂逻辑可移入 XML 文件以提高可读性。 - **测试**:确保空参数、边界值(如空字符串)被正确处理,避免运行时错误。 - **模糊查询安全**:始终用 `CONCAT` 或 `#{param}` 构建模糊模式,而非硬编码 `%`[^2]。 通过以上方法,您可以高效实现动态 SQL 查询,提升代码的灵活性和可维护性。如果您有具体场景(如分页或关联查询),可提供更多细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值