十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MyBatis通用查询如何避免SELECT *?MetaLite如何按需返回字段

MyBatis通用查询如何避免SELECT *?MetaLite如何按需返回字段 MyBatis 通用查询如何避免 SELECT *MetaLite 如何按需返回字段摘要MyBatis 手写 SQL 时当然可以精确选择列问题发生在通用 DAO为了复用查询逻辑很多项目退回SELECT *宽表、列表页和大字段读取随之浪费带宽。MetaLite ORM 把字段投影放进Query.includeField/excludeFieldfindOneByQuery与findListByQuery都能按需取字段而且支持方法引用字段重命名可获得编译期保护。先澄清一个事实MyBatis 并不会强迫开发者写SELECT *。它最大的优势之一正是 SQL 完全可控。真正的痛点是通用查询。条件、排序、分页都希望复用返回字段又因场景不同而变化。团队要么复制多条 SQL要么让公共方法查询整行数据。MetaLite ORM 将字段选择提升为Query的标准组成部分。一、findOne 和 findList 为什么都需要字段投影典型场景包括用户列表只需要 id、昵称和状态不需要头像原图或个人资料权限判断只需要 id 与状态定时任务只扫描主键和时间字段Elasticsearch 列表页只需要摘要不需要完整正文。如果只有少量字段读取整行会增加数据库 IO、网络传输、对象转换和 JVM 占用。宽表或大字段场景尤其明显。二、Query 同时支持 include 与 exclude只返回明确字段QueryqueryQuery.query(Criteria.where(UserEntity::getStatus,1)).includeField(UserEntity::getId,UserEntity::getNickname,UserEntity::getStatus);ListUserEntityusersuserDao.findListByQuery(query);排除少数大字段QueryqueryQuery.query(criteria).excludeField(UserEntity::getAvatar,UserEntity::getProfile);UserEntityuseruserDao.findOneByQuery(query);includeField、excludeField都提供字符串、字符串集合和方法引用重载。推荐业务代码优先使用方法引用实体字段改名后更容易在编译阶段发现影响范围。三、JDBC 最终如何生成 SELECT 列JdbcHelper.select(Query)遍历实体属性到数据列的映射字段出现在excludeFields中直接跳过没有设置includeFields默认选择其余所有字段设置了includeFields只加入明确包含的字段最终生成实际列名列表而不是固定SELECT *。因此 include 与 exclude 同时出现时exclude 拥有更高优先级。团队应避免写互相冲突的配置否则可读性会变差。还应保证最终至少保留一个有效字段。当前 JDBC SQL 生成逻辑会在拼接完成后删除最后一个逗号如果 include 中没有合法实体字段或所有字段又被 exclude 排除不能期待框架自动退回SELECT *。这类配置应在调用前校验并作为后续框架防御性校验的改进点。四、字段投影不只作用于列表查询BaseEntityDao提供findOneByQuery(Query)findListByQuery(Query)findListByQuery(Query, Pageable)。这意味着单对象查询、列表和分页列表都能复用相同的字段投影、条件、排序和 hints而不必为了返回列不同创建多个 Mapper 方法。Query默认 limit 为Pageable.MAX_PAGE_SIZE当前是 2000防止一个没有分页意识的通用查询无限拉取数据。Pageable还限制页码与页大小范围。五、MySQL 与 Elasticsearch 为什么共用同一选择方式在 JDBC 实现中字段投影生成 SQL 列表在 Elasticsearch 实现中对应的是 source filtering。业务代码仍通过Query.includeField/excludeField表达意图。切换数据源实现时调用层不用重新学习一套字段选择接口。这就是 MetaLite 自研 ORM 的核心方向不试图统一所有底层语法只统一企业应用最常见、最值得治理的访问语义。六、部分字段实体有一个容易踩的坑返回类型仍然是实体类。没有被查询的字段会保持 Java 默认值例如引用类型为null数值基本类型可能为0。这不代表数据库中真的存储了这些值。因此部分字段实体适合只读展示或后续投影不要把它直接当完整实体执行全字段更新返回给接口前最好转换成明确的 DTO基本类型若需要区分“未查询”和 0应考虑包装类型。字段投影减少 IO但也要求调用方理解“不完整实体”的语义。七、与 MyBatis-Plus Wrapper.select 有什么区别MyBatis-Plus 已经支持 LambdaQueryWrapper 的select同样可以避免字符串字段。这一点不应忽略。MetaLite 的差异主要不在“能不能选字段”而在组合后的契约字段投影与自研Criteria、Query、Pageable同属于 common 模块JDBC 与 Elasticsearch 消费同一查询对象findOne、findList、分页列表共享 DAO 语义与数据源组、DbRouter、TableRouter 一起工作。如果项目只使用 MySQL 且 MyBatis-Plus 已经治理良好仅为字段投影迁移 ORM 没有必要。八、真正值得优化的不是语法而是默认行为MetaLite 并没有发明“选择部分字段”。它做的是把这项能力变成通用 DAO 的默认组成部分并给字段方法引用、结果上限和多数据源实现一个共同入口。对于宽表和高频列表页这种统一约束比每次提醒开发者“别写 SELECT *”更容易长期执行。框架简介MetaLite 是面向企业生产环境的新一代 Java 微服务技术底座。系列文章重点分享代码背后的设计思路、技术取舍与工程实践。源码基线JDK 21、Spring Boot 3.2.9、Spring Cloud 2023.0.1、Spring Cloud Alibaba 2023.0.1.3具体组件版本以项目backend-bom为准。作者简介15 年 Spring 体系企业级开发经验专注于 Java 微服务架构、工程治理与生产实践。持续更新MetaLite 系列内容将持续更新围绕核心设计、源码链路、技术取舍与生产实践展开。欢迎关注作者及时获取后续内容。在线演示演示地址: https://admin.metalite.top/演示账号: guess演示密码: admin2026
返回列表