【Mybatis】@Select与@Update注解动态SQL实战精讲

MyBatis 3.5 注解动态SQL实战:5种@Select/@Update条件拼接与性能影响 本文深入探讨了MyBatis 3.5注解动态SQL的实战应用,详细解析了5种@Select/@Update条件拼接方法及其性能影响。通过具体代码示例,展示了如何使用<if>、<choose>、<where>、<set>和<foreach>等动态标签优化SQL查询,提升开发效率与系统性能。 阅读详情

1. MyBatis注解开发入门

如果你正在使用MyBatis框架,但又厌倦了XML配置文件的繁琐,那么注解开发绝对是你的福音。我刚开始接触MyBatis时,也是从XML配置入手的,后来发现注解方式简直不要太方便!特别是对于中小型项目,注解开发能显著提升编码效率。

@Select 和 @Update 是MyBatis中最常用的两个注解,它们可以直接在Mapper接口的方法上编写SQL语句。想象一下,以前我们需要在XML文件中写SQL,然后在接口中定义方法,现在直接在接口方法上写SQL,代码量直接减半!

// 传统XML方式需要额外编写映射文件
public interface UserMapper {
    User getUserById(Integer id);
}

// 注解方式直接在接口中完成
public interface UserMapper {
    @Select("SELECT * FROM users WHERE id = #{id}")
    User getUserById(Integer id);
}

不过要注意,注解方式虽然方便,但在处理复杂SQL时可能会显得力不从心。我在实际项目中发现,当SQL超过5行时,可读性就会明显下降。这时候就需要用到动态SQL标签来优化了。

2. @Select注解深度解析

2.1 基础查询用法

@Select 注解最基本的用法就是直接在注解中写SQL语句。我刚开始用时觉得特别神奇,Java代码里直接写SQL,还能自动映射结果!

@Select("SELECT id, username, email FROM users WHERE id = #{userId}")
User selectUserById(@Param("userId") Integer id);

这里有个小技巧:使用 @Param 注解明确指定参数名,这样在复杂SQL中更不容易出错。我曾经因为没加这个注解调试了半天,参数名对不上导致SQL执行失败。

2.2 结果集映射

当数据库字段名和Java属性名不一致时,我们可以用 @Results 和 @Result 注解来映射:

@Select("SELECT user_id, user_name, user_email FROM users")
@Results({
    @Result(property = "id", column = "user_id"),
    @Result(property = "username", column = "user_name"),
    @Result(property = "email", column = "user_email")
})
List<User> selectAllUsers();

在实际项目中,我建议字段名和属性名尽量保持一致,可以省去这些映射配置。如果必须使用不同命名,可以考虑在MyBatis配置中开启驼峰命名转换:

<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

2.3 动态SQL构建

这才是 @Select 注解真正强大的地方!通过 <script> 标签,我们可以在注解中使用各种动态SQL标签:

@Select("<script>" +
        "SELECT * FROM users " +
        "<where> " +
        "   <if test='username != null'>AND username = #{username}</if> " +
        "   <if test='email != null'>AND email = #{email}</if> " +
        "</where> " +
        "</script>")
List<User> selectUsersByCondition(@Param("username") String username, 
                                 @Param("email") String email);

我第一次看到这种写法时觉得很别扭,SQL被拆分成多个字符串用加号连接。但习惯后发现这种写法其实很灵活,特别是配合IDE的代码格式化功能后,可读性还不错。

3. @Update注解实战技巧

3.1 基础更新操作

@Update 注解的基本用法和 @Select 类似:

@Update("UPDATE users SET username = #{username}, email = #{email} WHERE id = #{id}")
int updateUser(User user);

这里要注意返回值是int类型,表示受影响的行数。在实际业务中,我建议总是检查这个返回值,确保更新操作确实生效了。

3.2 动态更新字段

在更新操作中,我们经常只需要更新部分字段。这时候 <set> 和 <if> 标签就派上用场了:

@Update("<script>" +
        "UPDATE users " +
        "<set> " +
        "   <if test='username != null'>username = #{username},</if> " +
        "   <if test='email != null'>email = #{email},</if> " +
        "</set> " +
        "WHERE id = #{id} " +
        "</script>")
int updateUserSelective(User user);

这里有个坑我踩过: <set> 标签会自动去掉最后一个逗号,所以即使最后一个 <if> 条件成立,生成的SQL也是正确的。刚开始我还手动处理逗号,结果发现根本不需要。

3.3 批量更新操作

批量更新是实际项目中很常见的需求,我们可以使用 <foreach> 标签实现:

@Update("<script>" +
        "UPDATE users " +
        "SET status = #{status} " +
        "WHERE id IN " +
        "<foreach collection='ids' item='id' open='(' separator=',' close=')'> " +
        "   #{id} " +
        "</foreach> " +
        "</script>")
int batchUpdateStatus(@Param("ids") List<Integer> ids, @Param("status") String status);

这种写法性能比在Java中循环执行单条更新要好得多。我在一个用户管理系统中使用后,批量操作耗时从秒级降到了毫秒级。

4. 高级应用与性能优化

4.1 多表关联查询

注解方式同样支持多表查询,只是SQL会变得比较长:

@Select("SELECT u.*, a.province, a.city " +
        "FROM users u LEFT JOIN addresses a ON u.id = a.user_id " +
        "WHERE u.id = #{userId}")
@Results({
    @Result(property = "id", column = "id"),
    @Result(property = "address.province", column = "province"),
    @Result(property = "address.city", column = "city")
})
User selectUserWithAddress(@Param("userId") Integer userId);

对于特别复杂的关联查询,我建议还是使用XML方式,可读性会更好。或者考虑使用 @One 和 @Many 注解实现延迟加载。

4.2 分页查询优化

分页查询在注解中的实现需要注意SQL方言问题:

// MySQL分页
@Select("SELECT * FROM users LIMIT #{offset}, #{pageSize}")
List<User> selectUsersByPage(@Param("offset") int offset, @Param("pageSize") int pageSize);

// Oracle分页(使用ROWNUM)
@Select("<script>" +
        "SELECT * FROM (" +
        "   SELECT a.*, ROWNUM rn FROM (" +
        "       SELECT * FROM users ORDER BY id" +
        "   ) a WHERE ROWNUM <= #{end}" +
        ") WHERE rn > #{start}" +
        "</script>")
List<User> selectUsersByPageForOracle(@Param("start") int start, @Param("end") int end);

在实际项目中,我推荐使用PageHelper这类分页插件,它们能自动识别数据库方言并生成合适的分页SQL。

4.3 二级缓存配置

注解方式也可以配置二级缓存,只需要在Mapper接口上添加 @CacheNamespace 注解:

@CacheNamespace(implementation = MyCustomCache.class, eviction = MyCustomCache.class)
public interface UserMapper {
    // 方法定义
}

关于缓存,我有过惨痛教训:在电商系统中,商品信息使用了缓存但没设置合适的过期策略,导致价格更新后前端显示的还是旧价格。所以使用缓存一定要谨慎,考虑好数据一致性问题。

5. 最佳实践与常见问题

5.1 注解与XML的选择策略

根据我的经验,以下情况适合使用注解:

  • SQL比较简单
  • 项目规模较小
  • 需要快速开发原型

以下情况建议使用XML:

  • SQL非常复杂
  • 需要大量动态SQL
  • 团队有专门的DBA负责SQL优化

其实两者可以混用,我在实际项目中经常这样做:简单的CRUD用注解,复杂的统计查询用XML。

5.2 SQL注入防护

注解方式同样需要注意SQL注入问题。MyBatis的 #{} 语法会预编译参数,是安全的。但使用 ${} 时要特别小心:

// 安全写法
@Select("SELECT * FROM users WHERE username = #{name}")
User findByUsername(@Param("name") String name);

// 危险写法(可能SQL注入)
@Select("SELECT * FROM ${tableName} WHERE username = #{name}")
User findByUsernameDynamicTable(@Param("tableName") String tableName, 
                               @Param("name") String name);

5.3 日志调试技巧

当注解SQL执行出错时,我常用的调试方法是开启MyBatis的完整日志:

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

这样可以在控制台看到实际执行的SQL和参数,非常方便排查问题。

5.4 代码组织建议

对于较长的注解SQL,我建议这样组织代码:

  1. 每个SQL方法保持单一职责
  2. 复杂SQL拆分成多行,用加号连接
  3. 使用IDE的代码格式化功能保持缩进
  4. 添加必要的注释说明SQL用途
@Select("<script>" +
        "/* 根据条件查询活跃用户 */ " +
        "SELECT u.id, u.username, u.email " +
        "FROM users u " +
        "<where> " +
        "   u.status = 'ACTIVE' " +
        "   <if test='keyword != null'> " +
        "       AND (u.username LIKE CONCAT('%', #{keyword}, '%') " +
        "           OR u.email LIKE CONCAT('%', #{keyword}, '%')) " +
        "   </if> " +
        "</where> " +
        "ORDER BY u.create_time DESC " +
        "</script>")
List<User> selectActiveUsers(@Param("keyword") String keyword);

这种写法虽然SQL被拆分成多个字符串,但通过良好的格式化和注释,可读性依然很高。

MyBatis注解开发全解析:从基础CRUD到动态SQL实战 在Java持久层框架中,SQL与代码的集成方式直接影响开发效率与维护性。MyBatis通过核心机制提供了两种主流方式:传统的XML映射与基于注解的声明式编程。注解方式利用`@Select`、`@Insert`等标准注解,将SQL语句直接内聚在接口方法上,实现了数据操作逻辑的紧耦合与快速开发。其技术价值在于简化配置、提升代码可读性,尤其适用于中小型项目或微服务架构中的简单静态SQL场景。然而,面对复杂动态SQL、批量操作等高级需求时,仍需结合XML或Provider类实现。本文聚焦**注解开发**的完整路径, 阅读详情

相关推荐

MyBatis 3.5+ 注解开发:@Select/@Update 动态SQL的3种实现与性能对比

随着3.5版本的发布,MyBatis在注解开发方面带来了更多可能性,特别是动态SQL的实现方式更加多样化。在实际项目中,我们团队发现对于中等复杂度的系统,结合注解与少量XML的混合模式往往能取得最佳平衡。特别是在需要动态表名、复杂联表查询等场景时,Provider类提供的灵活性远超纯注解方案。动态SQL是MyBatis最强大的特性之一,它允许我们根据运行时条件构建不同的SQL语句。在注解开发中,传统XML中的。注解下三种动态SQL实现方案,并通过JMH基准测试揭示性能差异,帮助开发者做出更明智的技术选型。

weixin_30386713的博客 300

MyBatis @Select注解介绍:基本用法与动态SQL拼写

这里写自定义目录标题 @Select注解的目的是为了取代xml中的select标签,只作用于方法上面。下面看一下@Select注解的源码介绍: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Select { String[] value(); } 从上述可以看到两点信息: (1)@Select注解只能修饰方法 (2)@Select注解的值是字符数组。 所以,@Select注解的用法

FastText的博客 9万+

Mybatis动态SQL注解开发操作数据库

在上面的示例中,@SelectProvider注解指定了Provider接口的类型和方法,Provider接口中包含了生成SELECT语句的方法getPersonFromProviderById。常用的注解有@Select,@Update,@Insert,@Delete等,它们分别用于配置查询,更新,插入和删除操作。在这个例子中,@InsertProvider注解指定了Provider接口的类型和方法,Provider接口中包含了生成INSERT语句的方法insertUser。2、编写Mapper接口。

码农从0到1 1075

【Mybatis】@Select与@Update注解写法总结

MyBatis 中的 `@Select` 注解用于直接在接口方法上编写 SQL 语句,避免了使用 XML 映射文件。`@Select` 注解的使用使得 SQL 语句的编写更加直观,并且可以直接与接口方法关联,提高了开发效率和代码的可读性。

慕白Lee的博客 1万+

MyBatis @Select/@Update 注解进阶:3种复杂结果映射与事务控制实践

本文深入解析MyBatis中@Select和@Update注解的高级应用,涵盖复杂结果映射的三种实现方式(@Results复用、嵌套映射@One/@Many、动态映射)、事务控制与批量操作优化,以及动态SQL构建技巧。通过实战案例演示多级联查与性能优化方案,帮助开发者掌握MyBatis注解开发的核心技术。

cishan3804的博客 307

ArcGIS符号库下载 | 制图规范、三调、1:1万地形图、土地利用总体规划图.....

最近整理了一些符号库 涉及的类型比较多 包含有三调的(二调的也加上去了),一些点线面符号库,1:1万地形图,1:5万土地利用,土地利用总体规划图

qq_43173805的博客 2万+

Mybatis 注解开发 + 动态SQL

Hello 大家好我是橙子同学,今天分享注解Mybatis注解开发+动态sql 目录 每文一铺垫(今天有小插曲哦) 注解开发 添加@Insert 删除@Delete 查询@Select 修改@Update 实现结果集封装@Result 实现一对一结果集封装@one 实现多对多结果集封装 @Many 动态SQL 标签<set> <if> 标签<wher...

m0_65729948的博客 1万+

天地图API避坑指南:从零开始实现地址搜索与坐标标记

本文是一份天地图API实战避坑指南,详细讲解了从申请密钥、初始化地图到实现地址搜索与坐标标记的全过程。针对开发中常见的坐标偏移、搜索建议不显示、事件监听失效等核心难题,提供了具体的解决方案和代码示例,帮助开发者高效、稳定地集成天地图服务。

weixin_29326909的博客 264

Mybatis注解用法

MyBatis(八) mybatis注解 一、mybatis简单注解 1、@Select、@Results、@Result 2、@Delete、@Param、@ResultMap 3、@Insert、@SelectKey 4、@Delete、@Param 5、@Update 二、动态SQL 1、简单处理,直接使用``脚本 2、使用Provider注...

u013452337的博客 5万+

服务器AutoDL自己部署QWen3

说明:核心参数:30B 模型原精度权重文件约 60GB,单张 PRO 6000 拥有 48GB 显存,单卡塞不下原精度模型,2张 PRO 6000 = 96GB 总显存,这不仅能装下模型,还能留出约 30GB 显存给 KV Cache(上下文长度) 以及 Omni 多模态组件 处理图片/视频输入时的额外开销。1. 前提准备模型选择:直接下载到 AutoDL 服务器上=》原精度模型(BF16/FP16) 的 Qwen3-Omni-30B,选择的示例和环境如下。# 3. 正式执行模型下载。

xiaoxiao_00001的博客 415

2026保姆级:1小时搞定C# OPC UA客户端开发——PLC与上位机全量数据交互零基础教程

本文介绍了使用C#开发OPC UA客户端的核心流程和关键代码实现。文章首先指出工业上位机开发中OPC UA的重要性,并针对新手常见问题提出了1小时掌握核心功能的解决方案。重点内容包括:选择官方.NET Standard库的优势、5分钟搭建开发环境的步骤、OPC UA客户端架构与通信流程的图解说明,以及完整的客户端基础类代码实现,涵盖了连接管理、证书配置、安全认证等关键功能。通过本文提供的代码模板,开发者可快速实现与PLC等工业设备的稳定数据交互。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 799

Mybatis使用注解实现复杂动态SQL

Mybatis使用注解实现复杂动态SQL

小张的博客 2961

PyTorch实战(12)——图神经网络(Graph Neural Network,GNN)

在本节中,我们首先简要概述了图神经网络 (Graph Neural Network, GNN) 的核心概念与应用,GNN 通过构建计算图分层聚合节点特征,解决了传统神经网络处理图数据时的四大局限:信息深度不足、节点顺序敏感、动态扩展困难和特征稀疏性问题。了解了不同类型的图学习任务(包括节点级、边级和图级三大类)。接着我们研究了几种流行的 GNN 模型,包括:GCN (通过权重共享实现图卷积)、GAT (引入注意力机制区分邻居重要性)和 GraphSAGE (采用随机采样应对大规模图)。

盼小辉丶的博客 3670

MyBatis @Update注解深度解析

在当今的软件开发领域,数据库操作是构建应用程序不可或缺的一环。特别是在使用MyBatis框架进行数据库交互时,@Update注解扮演着至关重要的角色。想象一下,一个电商系统在处理用户订单更新时,如果每次更新操作都需要手动编写SQL语句,不仅效率低下,而且容易出错。这就引出了MyBatis中@Update注解的必要性。@Update注解是MyBatis框架提供的一个用于定义更新操作的注解。它允许开发者通过简单的注解方式,将SQL更新语句与Java代码紧密绑定,从而简化数据库更新操作。

我是Java程序员廖志伟,感谢朋友们的支持!不定期贡献一篇高品质、过万文字、图文并茂且附有视频解说、满载代码示例注释的良心之作,坚决杜绝粗制乱造。 1160

宇树科技嵌入式面试题及参考答案(春晚机器人的公司)

内存对齐是指在内存中为数据对象分配存储空间时,按照一定的规则将数据存储在特定的地址上,以提高内存访问效率。不同的数据类型在内存中都有其特定的对齐要求,例如,int类型通常要求 4 字节对齐,double类型通常要求 8 字节对齐。这意味着数据的存储地址必须是其对齐字节数的整数倍。如果不进行内存对齐,处理器在访问数据时可能需要进行多次内存访问,从而降低了访问效率。指令可以用于控制结构体内存布局,它允许程序员指定结构体成员的对齐方式。其基本用法是在结构体定义之前使用来指定对齐字节数n,其中n。

大模型大数据攻城狮的专栏 3226

【第一章】基于Simulink的控制器开发教程——目录

摘要:本文系统介绍了基于Simulink的控制器开发方法,涵盖PID、状态反馈、模型预测(MPC)、模糊控制、自适应控制等8类主流控制器。针对每种控制器,详细阐述了其基本原理、适用场景,并通过Simulink建模与仿真测试进行实践验证。文章采用"理论+实践"的结构,从算法设计到硬件实现全流程展开,为汽车、航空航天、工业控制等领域的控制器开发提供完整解决方案,最后通过应用对比与学习总结帮助读者掌握不同控制器的核心特性和应用场景。(149字)

熟悉MATLAB/fpga/RK3588/LABVIEW/protus/单片机/dsp/Multisim 389

MyBatis @Select注解深度解析

在当今的软件开发领域,数据库操作是构建应用程序不可或缺的一部分。特别是在使用MyBatis框架进行数据库交互时,@Select注解扮演着至关重要的角色。想象一下,一个典型的企业级应用,其业务逻辑往往涉及大量的数据库查询操作。如果这些操作不能高效、准确地执行,那么整个应用的性能和稳定性都将受到严重影响。在这种背景下,介绍MyBatis核心知识点之@Select:概述显得尤为重要。

我是Java程序员廖志伟,感谢朋友们的支持! 1575

微信小程序 - 实现客户支付订单连接小票打印机自动打印订单小票功能,微信小程序如何对接小票打印机自动打印小票,小程序收到新订单的时候可以联动商家打印出小票/单据/标签/发货单/电子面单等(详细教程)

微信小程序调用小票打印机,小程序接单后小票机自动打印订单,微信小程序云开发订单微信支付与小票和标签打印的完整高效流程,如何实现微信订单连接小票打印机并自动接单打印,微信小程序连接打印机打印单据小票打印,微信小程序云开发调用小票打印机实现方案,微信小程序怎么配置小票打印机,微信支付电子小票,外卖小程序实战-接单后小票机自动打印订单,微信小程序连接蓝牙打印小票,打印购物小票,调用小票打印机打印小票,微信订单如何连接小票打印机并实现自动接单打印,实现微信订单连接小票打印机并自动接单打印,微信小程序小票打印机打印教

🏆 前端领域优质创作者 1万+

Mybatis 注解写法( 附10余个常用例子 )

【前言】 Mybatis 除了 XML 配置写法,还可以使用注解写法。 首先需要引入 Mybatis 的依赖: <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifact...

小白一个 4785

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Mybatis 之九:MyBatis 注解

在 MyBatis 框架中,注解可以用于替代或补充 XML 映射文件来实现 SQL 语句的映射。使用注解可以使代码更简洁,减少配置文件的工作量,特别适用于简单场景和快速开发。使用@Results() 注解时,通过id属性来唯一标识结果映射,其他的方法可以通过 @ResultMap()直接引用。所以需要修改对应的 IEmpDao 和 IDeptDao 两个接口,那这样就需要在配置文件中同时配置两个dao的。修改员工持久接口 IEmpDao,新增通过部门编号查询员工列表的方法。修改 IDeptDao 接口。

zp8126的专栏 2194

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

上一篇: AD不行就帮打野起飞:从战术口号到实战节奏运营详解
下一篇: M7 Ultra 1.5TB统一内存架构:AI训练与8K视频编辑的性能突破
liudaoru
博客等级 码龄18年 5粉丝 302原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值