跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Spring数据查询
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Spring数据查询 = == 概述 == '''Spring数据查询'''是Spring Data模块的核心功能之一,它允许开发者通过简单的方法命名约定、注解或自定义查询语言(如JPQL、Native SQL)来访问和操作数据库。Spring Data提供了统一的抽象层,支持多种数据存储技术(如JPA、MongoDB、Redis等),显著减少了样板代码的编写。 Spring数据查询的主要特点包括: * '''方法名派生查询''':通过解析方法名自动生成查询 * '''@Query注解''':支持JPQL或原生SQL * '''动态查询''':通过`Specification`或`QueryDSL`实现复杂条件组合 * '''分页与排序''':内置支持 == 查询方法类型 == === 方法名派生查询 === Spring Data可以通过解析Repository接口中的方法名自动生成查询。规则如下: <syntaxhighlight lang="java"> public interface UserRepository extends JpaRepository<User, Long> { // 根据属性名查询 List<User> findByLastName(String lastName); // 多条件查询 List<User> findByFirstNameAndLastName(String firstName, String lastName); // 排序 List<User> findByAgeGreaterThan(int age, Sort sort); // 分页 Page<User> findByActiveTrue(Pageable pageable); } </syntaxhighlight> 命名约定: * 关键字:`findBy`、`readBy`、`queryBy`、`countBy`、`deleteBy` * 条件:`And`、`Or`、`Between`、`LessThan`、`Like`、`IgnoreCase` * 排序:`OrderBy[属性]Asc/Desc` === @Query注解 === 对于复杂查询,可以使用`@Query`注解定义JPQL或原生SQL: <syntaxhighlight lang="java"> @Query("SELECT u FROM User u WHERE u.email LIKE %?1%") List<User> findByEmailContaining(String emailPart); @Query(value = "SELECT * FROM users WHERE registration_date > ?1", nativeQuery = true) List<User> findRegisteredAfter(Date date); </syntaxhighlight> == 动态查询 == === Specification接口 === 实现`JpaSpecificationExecutor`接口后,可以使用`Specification`构建动态查询: <syntaxhighlight lang="java"> public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {} // 使用示例 Specification<User> spec = (root, query, cb) -> { List<Predicate> predicates = new ArrayList<>(); if (name != null) { predicates.add(cb.like(root.get("name"), "%" + name + "%")); } if (minAge != null) { predicates.add(cb.ge(root.get("age"), minAge)); } return cb.and(predicates.toArray(new Predicate[0])); }; List<User> users = userRepository.findAll(spec); </syntaxhighlight> === QueryDSL集成 === 更类型安全的动态查询方案: <syntaxhighlight lang="java"> QUser user = QUser.user; BooleanExpression predicate = user.firstName.contains("John") .and(user.age.between(20, 30)); Iterable<User> users = userRepository.findAll(predicate); </syntaxhighlight> == 分页与排序 == Spring Data提供开箱即用的分页支持: <syntaxhighlight lang="java"> Pageable pageable = PageRequest.of(0, 10, Sort.by("lastName").ascending()); Page<User> page = userRepository.findByActiveTrue(pageable); // 获取结果 List<User> content = page.getContent(); int totalPages = page.getTotalPages(); </syntaxhighlight> == 投影与DTO == 可以定义接口投影或类投影来返回部分字段: <syntaxhighlight lang="java"> // 接口投影 public interface NameOnly { String getFirstName(); String getLastName(); } List<NameOnly> users = userRepository.findByDepartment("IT"); // 类投影 @Query("SELECT new com.example.UserDto(u.firstName, u.lastName) FROM User u") List<UserDto> findUserDtos(); </syntaxhighlight> == 性能优化 == === 实体图 === 通过`@EntityGraph`定义关联加载策略: <syntaxhighlight lang="java"> @EntityGraph(attributePaths = {"addresses", "roles"}) List<User> findAllWithAddressesAndRoles(); </syntaxhighlight> === 批量处理 === 使用`@Modifying`进行批量更新: <syntaxhighlight lang="java"> @Modifying @Query("UPDATE User u SET u.active = ?2 WHERE u.id IN ?1") int updateActiveStatus(List<Long> ids, boolean active); </syntaxhighlight> == 实际案例 == === 电商平台商品搜索 === <mermaid> graph TD A[前端请求] --> B(Controller) B --> C{参数解析} C -->|简单条件| D[方法名派生查询] C -->|复杂条件| E[Specification构建] D & E --> F[Repository执行] F --> G[返回分页结果] </mermaid> 实现代码: <syntaxhighlight lang="java"> public Page<Product> searchProducts(String name, BigDecimal minPrice, BigDecimal maxPrice, String category, Pageable pageable) { Specification<Product> spec = (root, query, cb) -> { List<Predicate> predicates = new ArrayList<>(); if (StringUtils.hasText(name)) { predicates.add(cb.like(root.get("name"), "%" + name + "%")); } if (minPrice != null) { predicates.add(cb.ge(root.get("price"), minPrice)); } if (maxPrice != null) { predicates.add(cb.le(root.get("price"), maxPrice)); } if (StringUtils.hasText(category)) { predicates.add(cb.equal(root.get("category").get("name"), category)); } return cb.and(predicates.toArray(new Predicate[0])); }; return productRepository.findAll(spec, pageable); } </syntaxhighlight> == 数学表达式示例 == Spring Data JPA中的分页总页数计算: <math> totalPages = \lceil \frac{totalElements}{pageSize} \rceil </math> 其中: * <math>totalElements</math> = 总记录数 * <math>pageSize</math> = 每页大小 == 总结 == Spring数据查询提供了多种灵活的方式来访问数据: * 简单查询优先使用方法名派生 * 复杂查询使用`@Query`或`Specification` * 动态查询考虑`QueryDSL` * 性能敏感场景使用投影和实体图 * 大数据量操作使用批量处理 通过合理组合这些技术,可以在保持代码简洁的同时满足各种业务查询需求。 [[Category:后端框架]] [[Category:Spring]] [[Category:Spring数据]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)