首页 文章 精选 留言 我的

精选列表

搜索[字节级],共10000篇文章
优秀的个人博客,低调大师

MyBatis 史诗级的裹脚布可以烧了!!!

作为一名 Java 开发者,你一定经历过被 MyBatis XML 支配的恐惧。 当你打开一个UserMapper.xml,迎面而来的是几百行甚至上千行的<if>,<where>,<choose>,<foreach>标签。原本清爽的 SQL 语句被这些 XML 标签切割得支离破碎,仿佛老太太的裹脚布——又臭又长。 如果你也受够了在 XML 标签里写逻辑,受够了为了一个简单的非空判断就要写三行 XML,那么请继续往下看。dbVisitor 的动态 SQL 规则机制,也许就是你一直在寻找的"剪刀"。 MyBatis 的 XML 地狱​ 让我们先回顾一下,一个标准的、带有几个查询条件的 MyBatis SQL 是什么样子的: <select id="queryUsers" resultType="User"> SELECT * FROM tb_user <where> <if test="name != null"> AND name = #{name} </if> <if test="age != null"> AND age = #{age} </if> <if test="status != null"> AND status = #{status} </if> <if test="createTime != null"> AND create_time >= #{createTime} </if> </where> </select> 这段代码的问题在哪里,已经不用多言!这种一坨一坨的开发体验看到就难受至极,更别提还要去维护它。 革命性的解法​ dbVisitor 作为一个新一代的数据库访问工具,最核心的设计理念之一就是:让 SQL 回归 SQL。 利用 dbVisitor 独创的规则机制,上面的 XML 代码可以精简为: SELECT * FROM tb_user @{and, name = :name} @{and, age = :age} @{and, status = :status} @{and, create_time >= :createTime} 假设只传入参数name="Tom",生成的 SQL 如下: SELECT * FROM tb_user WHERE name = ? 是不是瞬间清爽了?没有了尖括号的视觉干扰,没有了冗余的 XML 闭合标签,只有纯粹的 SQL 逻辑。 你可能会问:@{and, ...}到底做了什么?它是简单的字符串拼接吗? 当然不是!dbVisitor 的规则引擎是非常智能的。以@{and, name = :name}为例,它内置了以下逻辑: 智能判空:引擎会自动检查key = :key表达式中的参数。如果参数:key为null,整个@{and}规则块会被自动忽略,不会生成任何 SQL(注意:空字符串""被视为有效值,不会忽略)。 WHERE 处理:如果内容不为空,@{and}会识别它是否是 WHERE 子句的开头。如果是开头(例如前面没有1=1),它会自动抹去AND,直接生成WHERE name = ?(这一点类似 MyBatis 的<where>标签,但更加隐形)。 这一切都是自动发生的,你只需要声明规则,剩下的交给 dbVisitor。 条件判断本该如此性感​ MyBatis 中 90% 的<if>标签都是为了做两件事: 参数不为空时,追加查询条件。 开关开启时,追加查询条件。 dbVisitor 将这两类高频场景直接内化为最基础的规则,无需任何复杂的标签嵌套。 1. 智能补全 自动检查条件状态选择是否需要自动补全WHERE/AND/OR关键字。 -- 唯一条件下,自动补全 WHERE SELECT * FROM tb_user @{and, name = :name} -- 多组条件中,自动追加 AND SELECT * FROM tb_user where type = 'employee' @{and, name = :name} -- 生成 and name = ? 2. 智能判空:@{and}/@{or} 这是你最常用的规则。它们会自动检查参数是否为null。 SELECT * FROM tb_user @{and, name = :name} -- 仅当 name 不为空时生成 and name = ? @{or, age > :age} -- 仅当 age 不为空时生成 or age > ? 3. 开关控制:@{ifand}/@{ifor} 当你需要用布尔值来控制 SQL 时,使用@{ifand}或@{ifor}。 -- 只有当 showAll 为 false 时,才拼接入 AND is_delete = 0 SELECT * FROM tb_user @{ifand, !showAll, is_delete = 0} 对比 MyBatis 的臃肿写法以及像老鼠屎一样无处不在的1=1 SELECT * FROM tb_user WHERE 1=1 <if test="!showAll"> AND is_delete = 0 </if> 仅仅是一个简单的条件,dbVisitor 让你少写了 3 行代码,减少无用的条件判断,这就是效率。 一行代码的 IN 查询​ MyBatis 的<foreach>标签简直是反人类设计:collection, item, open, close... 配置项多达七八个。 而且为了防止集合为空导致 SQL 语法错误,通常还得在外面套一层<if>,简直令人窒息: SELECT * FROM tb_user WHERE 1=1 <!-- 先判断不为空,再循环 --> <if test="idList != null and idList.size() > 0"> AND id IN <foreach collection="idList" item="id" open="(" separator="," close=")"> #{id} </foreach> </if> 而在 dbVisitor 中,利用@{ifand}和@{in}两个规则的嵌套使用,你只需要一行: -- ifand 接受 OGNL 表达式,!idList.isEmpty 确保集合有值时才生成 SQL SELECT * FROM tb_user @{ifand, !idList.isEmpty, id IN @{in, :idList}} 对比一下,这代码量节省的可不是一点点,而是降维打击! 忘掉 <set>:忘掉逗号​ 在写 Update 语句时,处理末尾的逗号是最烦人的。dbVisitor 的@{set}规则完美解决,引擎会自动处理字段间的逗号: UPDATE tb_user SET @{set, name = :name} @{set, age = :age} @{set, email = :email} WHERE id = #{id} MyBatis 用了一个<set>标签来解决这个问题: UPDATE tb_user <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} ⚠️ 虽然@{set}规则很强大,但规则的判断是依赖已经生成的 SQL 进行推断。 当规则没有匹配时,一些意外情况 UPDATE tb_user SET @{set, name = :name}, -- ❌ 规则无法删除身后的逗号 fixed_col = 123, @{set, email = :email} -- ❌ 规则虽然不会添加新的逗号但也不会删除上一个条件中的逗号 WHERE id = :id -- 正确的写法是 UPDATE tb_user SET fixed_col = 123 -- 先写固定列,再写动态列 @{set, name = :name} -- 规则会自动处理前置逗号 @{set, email = :email} WHERE id = :id 分支判断的救星​ MyBatis 的<choose>-<when>-<otherwise>结构冗长得令人发指,写起来仿佛在填表。 最大的麻烦在于即便是使用@Select注解仍然逃脱不了 XML 的魔咒 SELECT * FROM t_blog WHERE 1 = 1 <choose> <when test="title != null"> AND title = #{title} </when> <when test="content != null"> AND content = #{content} </when> <otherwise> AND owner = "defaultOwner" </otherwise> </choose> @Select({"<script>...无法逃避的 XML 魔咒...</script>"}) List<Blog> queryBlogs(@Param("title") String title, @Param("content") String content); dbVisitor 让你用 SQL 的思维写 SQL,更符合编程直觉。同样的场景,dbVisitor 只需要这样: CASE 规则 IF-ELSE 模式 SELECT * FROM t_blog @{and, @{case, , @{when, title != null, title = #{title}}, @{when, content != null, content = #{content}}, @{else, owner = "defaultOwner"} } } 换一个例子:根据 encryptMode 的值选择加密方式 CASE 规则 Switch 模式 SELECT * FROM tb_user @{and, @{case, encryptMode, @{when, true, password = @{md5, :pwd}}, @{else, password = :pwd} } } 像乐高积木一样组合​ 规则引擎最强大的地方在于其可组合性。所有规则都可以像乐高积木一样嵌套使用。这意味着你可以用@{case}的结果去驱动@{and},或者在@{else}里再写一组@{if}。 比如一个常见的权限控制场景: 如果是管理员 (ADMIN),查询所有数据; 如果是部门经理 (MGR),查询本部门数据; 如果是普通员工,只能查自己的数据。 SELECT * FROM tb_report @{and, @{case, role, @{when, 'ADMIN', /* 不加限制 */}, @{when, 'MGR', dept_id = :deptId}, @{else, user_id = :userId} } } 注意看,外层的@{and}会自动处理连接词: 当role是 'ADMIN' 时,@{case}输出空,整个@{and}消失。 生成SELECT * FROM tb_report WHERE 1=1。 当role是 'MGR' 时,内部输出dept_id = ?,外层自动加上AND。 生成... WHERE 1=1 AND dept_id = ?。 这种自然的嵌套组合,让你能用 SQL 结构直接表达复杂的业务逻辑,而不是在 Java 代码和 XML 之间反复横跳。 这就结束了?​ 规则的强大之处在于无处不在。你不需要为了使用动态 SQL 而强迫自己切换开发模式。无论你身处哪个层级,dbVisitor 的动态规则都能无缝集成。 1. 在 编程式 API (JdbcTemplate) 中使用 不需要 StringBuilder,不需要拼接字符串。 // 直接在 SQL 字符串中使用规则 jdbcTemplate.queryForList("SELECT * FROM users @{and, name = :name}", args); 2. 在 声明式 API (注解) 中使用 彻底摆脱@Script或者<script>标签的包裹,像写普通 SQL 一样写动态 SQL。 // 在 Mapper 接口的注解中使用 @Insert("INSERT INTO users (account, password) VALUES (:account, @{md5, :password})") int insertUser(User user); 3. 在 传统 XML 文件 中使用 如果你还是喜欢将 SQL 独立管理,dbVisitor 也支持在 XML 文件中使用这些规则,完全替代<if>等标签。 <select id="queryUser"> SELECT * FROM users @{and, name = :name} @{and, age = :age} </select> 这意味着可以将动态 SQL 的能力带入到任何你熟悉的地方,而不需要任何额外的适配成本。 结语​ 扔掉你的“裹脚布”,让我们来一场直观的对比: 特性 MyBatis XML dbVisitor 规则 评价 条件判断 <if test="...">...</if> @{and, ...} dbVisitor 节省 70% 代码量 IN 查询 <foreach item="..." ...> auto expand 直觉式编程 代码风格 XML 与 SQL 混杂 脚本化 SQL dbVisitor 阅读更流畅 维护成本 高,容易淹没在标签海中 低,逻辑一目了然 降本增效 技术在进步,工具在迭代。MyBatis 在过去的十几年里确实为 Java 生态做出了巨大贡献,但在动态 SQL 的处理上,它的 XML 方案确实显得过于陈旧和繁琐了。 dbVisitor 通过引入脚本化的规则引擎,在保留 SQL 灵活性的同时,彻底解决了动态 SQL 拼接的痛点。它向我们证明了:强大的功能不需要复杂的配置。 如果你厌倦了维护几千行的 XML Mapper,不妨试试 dbVisitor,体验一下"把裹脚布烧了"之后的奔跑快感。 项目首页:https://www.dbvisitor.net/ 项目源码:https://gitee.com/zycgit/dbvisitor/ 原文:https://www.dbvisitor.net/blog/mybatis-xml-vs-dbvisitor-rules

优秀的个人博客,低调大师

Resemble AI 全面开源旗舰级 TTS 模型

初创公司 Resemble AI 在 MIT 协议下开源了名为“Chatterbox Turbo”的文本转语音模型。这款模型在性能上实现了显著突破,仅需五秒钟的参考音频即可精准克隆目标语音,并在短短150毫秒内输出首个音频片段。 这种极致的低延迟表现,使其成为构建实时 AI 代理、自动化客户支持、动态游戏角色、虚拟形象以及社交平台交互的理想选择。Resemble AI 声称,该模型在语音质量上已超越现有闭源竞品,能为开发者提供更自然的合成体验。 在安全合规方面,Chatterbox Turbo 针对受监管行业内置了名为“PerTh”的神经水印功能,可用于验证语音的 AI 生成身份,有效应对深度伪造风险。 目前,Resemble AI 已同步提供托管服务,并计划在近期推出进一步优化延迟的版本,旨在通过开源生态重塑语音合成市场的竞争格局。

优秀的个人博客,低调大师

十亿级性能验证的隐私计算开源利器

在数据驱动的时代,我们每天都在产生大量数据:购物记录、健康信息、社交关系......这些数据蕴含巨大价值,但也伴随着隐私泄露的风险。 试想一下: 医院希望联合研究某种疾病,但患者数据无法直接共享。 银行想合作分析反欺诈信息,但客户隐私数据必须严格保护。 AI 公司需要使用大量用户数据训练模型,但用户对自己数据的使用方式几乎无法控制。 传统的数据共享方式就像在数据世界里「裸奔」,风险巨大。那么,有没有一种方法能在保护隐私的前提下实现数据的价值共享呢?隐私计算技术应运而生,它能让数据在加密状态下完成计算,真正做到「数据可用不可见」。 一、为什么要关注隐私计算? 隐私计算的兴起主要源于两个趋势: 法规严格:欧盟《通用数据保护条例》(GDPR)、中国《数据安全法》《个人信息保护法》等法规都对数据隐私提出了严格要求; 业务诉求紧迫:数据孤岛现象阻碍了各个行业创新突破,隐私计算成为平衡隐私安全与数据价值的桥梁。 到了 2025 年,随着生成式 AI 的普及,「AI 生成内容的归属权」已成为数据隐私领域的焦点问题。当企业利用用户数据训练 AI 模型时,谁拥有最终生成内容的权利?数据提供者如何确保自己的隐私不被侵犯? 面对这些挑战,今天我们将介绍一款当前非常流行且易用的隐私计算框架------SecretFlow(隐语),它能让数据在加密状态下完成计算,真正实现"可用不可见"的隐私保护理念。 GitHub 地址:github.com/secretflow/secretflow 最令人惊喜的是,只要你会 Python 就能通过 SecretFlow(隐语)快速上手这一前沿技术。本教程将带你一步步体验隐私计算的神奇与乐趣,让你在数据安全与价值之间找到完美平衡点! 接下来,让我们开始 SecretFlow 的奇妙之旅吧! 二、SecretFlow 是什么? SecretFlow 是由蚂蚁密算团队开源的可信隐私计算框架,它就像数据世界的"安全卫士",让数据在不暴露具体内容的情况下安全地进行计算和分析。有了 SecretFlow,不同机构可以像「戴着眼罩一起玩游戏」,既能高效地协作完成任务,又不会泄露各自数据。 2.1 优势 统一集成,一站式搞定:内置安全多方计算、联邦学习、差分隐私等主流隐私计算技术,无需再单独学习多个框架。 原生易用,零门槛上手:支持 SQL、Python 和 AI 等开发接口,用户可以快速上手减少学习成本。 灵活拓展,积木式架构:模块化设计,方便根据业务需求自由扩展和组合,快速迭代轻松应对业务变化。 高性能,经过大规模数据验证:在金融、医疗等实际场景中经过验证,处理数十亿级数据稳稳当当,性能优越可靠。 2.2 典型应用场景 医疗研究:医院可以使用 SecretFlow 进行联合研究,不需要共享患者的原始数据,即可进行数据分析,保护患者隐私。 金融反欺诈:银行可以合作分析反欺诈信息,使用 SecretFlow 确保客户的隐私数据不被暴露。 跨公司合作:多个企业可以在不暴露各自数据的前提下,通过 SecretFlow 进行联合数据分析,提升业务合作的效率和安全性。 AI 模型训练:AI 公司可以利用 SecretFlow 在保护用户隐私的前提下,使用大量用户数据训练模型,保证用户数据的安全。 三、快速上手:你的第一个 SecretFlow 程序 要体验 SecretFlow 很简单,官方提供 Docker 镜像,包含完整依赖直接启动即可使用。 3.1 安装步骤 你可以选择完整版本或 lite 版本(不包含深度学习)。 # 完整版本 docker run -it secretflow/secretflow-anolis8:latest # Lite 版本(更小巧) docker run -it secretflow/secretflow-lite-anolis8:latest 3.2 安全多方计算从零到一 我们用一个简单的例子「安全多方计算」来实际体验一下 SecretFlow,如何实现数据的「可用不可见」。 什么是安全多方计算? 安全多方计算(Secure Multi-Party Computation,MPC)是一种密码学技术,允许多个参与方在保护隐私的情况下,共同完成计算任务。 举个例子: Alice、Bob 和 Carol 想知道他们三人的平均收入,但又不想泄露各自的收入数额。安全多方计算可以让他们输入各自数据后,仅输出最终平均值,而不暴露任何人的具体收入。 我们后续会用到几个概念: 参与方(Party):拥有数据并参与计算的实体; 计算协议(Protocol):确保数据安全计算的规则; 秘密共享(Secret Sharing):将敏感数据拆分为多个碎片,单个碎片无法还原原始数据,只有足够多碎片组合才能还原。 3.3 快速体验:使用 SecretFlow 安全计算三人收入平均值 前面我们介绍了安全多方计算(MPC)的基本概念。接下来,我们以一个具体实例来展示 SecretFlow 如何让多个参与方安全计算数据的平均值,而不暴露任何人的具体收入数据。 场景回顾 Alice、Bob 和 Carol 想计算他们三个人的平均收入,但又不想让彼此知道各自具体的收入。这是典型的安全多方计算应用场景。 第一步:初始化隐私计算环境(创建参与方集群) 首先,我们创建一个本地模拟环境,包含三个参与方:Alice、Bob 和 Carol。 import secretflow as sf # 初始化 SecretFlow 本地模拟环境,包含三个参与方 sf.init( parties={'Alice', 'Bob', 'Carol'}, address='local' ) 第二步:为每个参与方创建隐私计算设备(PYU 设备) 每个参与方都会使用专属的计算设备来保存自己的数据。我们分别为 Alice、Bob 和 Carol 创建设备: alice = sf.PYU('Alice') bob = sf.PYU('Bob') carol = sf.PYU('Carol') 第三步:各参与方安全地输入自己的收入数据 为保护隐私,每个参与方通过自己的设备输入各自的收入数据: # 假设 Alice、Bob 和 Carol 的收入分别是 5000、6000 和 7000 alice_income = alice(lambda: 5000)() bob_income = bob(lambda: 6000)() carol_income = carol(lambda: 7000)() 注意: 每个参与方的数据只存在于自己的专属设备内。 其他参与方无法直接访问到这份数据。 第四步:使用安全多方计算协议,计算收入平均值 我们使用 SecretFlow 提供的安全计算协议(例如 SPU 设备)来安全地计算三个人的平均收入: # 创建一个安全计算设备(SPU),用于多方安全计算 spu = sf.SPU(sf.utils.testing.cluster_def(['Alice', 'Bob', 'Carol'])) # 将三人的收入数据安全地汇总到 SPU 设备,并计算平均值 average_income = spu(lambda x, y, z: (x + y + z) / 3)(alice_income, bob_income, carol_income) 在此过程中: Alice、Bob 和 Carol 的收入数据以加密或秘密共享的形式送入 SPU 设备。 SPU 设备安全地完成计算,参与方无法访问彼此的原始数据。 第五步:安全地查看计算结果(平均收入) 直接打印结果会看到一个加密后的对象: print(average_income) # 输出示例:<SPUObject object at 0x7fdec24a15b0> 此时数据仍处于加密状态,我们需要使用 sf.reveal 方法安全地解密并查看结果: # 安全地解密并查看结果 print("三人收入的平均值是:", sf.reveal(average_income)) # 输出:三人收入的平均值是: 6000.0 # 即 (5000+6000+7000)/3 = 6000 小结 通过本实例,我们完整体验了 SecretFlow 如何在保护数据隐私的前提下实现安全多方计算。每位参与方输入了自己的敏感数据,却不会暴露给其他人,最终大家都得到了想要的计算结果(平均收入),真正实现了数据「可用不可见」。 四、技术架构 SecretFlow 通过以下几个层次来实现隐私保护的数据分析和机器学习: 抽象设备层:由普通设备和秘密设备组成,秘密设备封装了各种加密协议。 设备流层:将更高层次的算法建模为设备对象流和DAG。 算法层:用于处理水平或垂直分区数据进行数据分析和机器学习。 工作流层:无缝集成数据处理、模型训练和超参数调整。 此外,SecretFlow 还关联了多个相关项目,如 Kuscia(一个轻量级隐私保护计算任务编排框架)、SCQL(一个允许多个不信任方联合分析的系统)、SPU(一个提供计算能力并保护私有数据的安全计算设备)、HEU(一个高性能同态加密算法库)和 YACL(一个包含密码学、网络和 IO 模块的 C++ 库)。 我们可以把 SecretFlow 想象成一座数字化的「智能工厂」: 数据全程加密保护:数据就像工厂的贵重原料,从进入工厂就被锁入保险柜(全程加密),计算时决不泄露。 安全高效跨团队合作:不同机构好比不同车间工人,彼此协作却不暴露原始数据。 高效计算不卡顿:工厂拥有高效自动化设备(高性能计算引擎),处理数据又快又稳。 灵活扩展适应需求:模块化设计,像乐高积木般灵活拼装,快速适应各种行业和需求。 五、最后 由于篇幅有限,上面的内容仅介绍了 SecretFlow(隐语)的冰山一角。它不仅让上手隐私计算变得简单,也让数据安全不再成为数据价值释放的阻碍。无论你是开发者、研究人员还是数据分析师,SecretFlow 都能助你轻松开启隐私计算之旅。 GitHub 地址:github.com/secretflow/secretflow 如果你想进一步了解更多 SecretFlow 实践案例和高级用法,欢迎访问官方开源社区参与讨论、贡献代码,一起为开源贡献力量吧!

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册