@RepositorypublicinterfaceKnowledgeRepositoryextendsJpaRepository<KnowledgeBaseEntity,Long>{// 方法名查询 - 按向量化状态查找List<KnowledgeBaseEntity>findAllByVectorStatusOrderByUploadedAtDesc(VectorStatusstatus);// 方法名查询 - 按分类查找List<KnowledgeBaseEntity>findByCategoryOrderByUploadedAtDesc(Stringcategory);// 方法名查询 - 模糊搜索Optional<KnowledgeBaseEntity>findByFileHash(StringfileHash);// JPQL 查询@Query("SELECT k FROM KnowledgeBaseEntity k WHERE LOWER(k.name) LIKE LOWER(CONCAT('%', :keyword, '%'))")List<KnowledgeBaseEntity>searchByKeyword(@Param("keyword")Stringkeyword);// 聚合查询@Query("SELECT COALESCE(SUM(k.accessCount), 0) FROM KnowledgeBaseEntity k")longsumAccessCount();// 原生 SQL 查询@Query(value="SELECT DISTINCT category FROM knowledge_bases WHERE category IS NOT NULL ORDER BY category",nativeQuery=true)List<String>findAllCategories();}
方法命名规则
JPA 支持通过方法命名自动生成查询,方法名遵循特定规则:
常用关键字
关键字
示例
生成的 SQL
findBy
findByName(String name)
WHERE name = ?
findByNameContaining
findByNameContaining(String keyword)
WHERE name LIKE '%keyword%'
findByNameStartingWith
findByNameStartingWith(String prefix)
WHERE name LIKE 'prefix%'
findByAgeGreaterThan
findByAgeGreaterThan(int age)
WHERE age > ?
findByAgeBetween
findByAgeBetween(int min, int max)
WHERE age BETWEEN ? AND ?
findByNameOrAge
findByNameOrAge(String name, int age)
WHERE name = ? OR age = ?
findByNameOrderByAgeDesc
findByNameOrderByAgeDesc(String name)
WHERE name = ? ORDER BY age DESC
countBy
countByName(String name)
SELECT COUNT(*) WHERE name = ?
existsBy
existsByName(String name)
SELECT COUNT(*) > 0 WHERE name = ?
deleteBy
deleteByName(String name)
DELETE FROM ... WHERE name = ?
JPQL 与原生 SQL
JPQL(Java Persistence Query Language)
1
2
@Query("SELECT k FROM KnowledgeBaseEntity k WHERE LOWER(k.name) LIKE LOWER(CONCAT('%', :keyword, '%')) ORDER BY k.uploadedAt DESC")List<KnowledgeBaseEntity>searchByKeyword(@Param("keyword")Stringkeywords);
原生 SQL
1
2
@Query(value="SELECT * FROM knowledge_bases WHERE file_hash = :hash",nativeQuery=true)Optional<KnowledgeBaseEntity>findByFileHashNative(@Param("hash")StringfileHash);
更新和删除
1
2
3
4
5
6
7
@Modifying@Query("UPDATE KnowledgeBaseEntity k SET k.vectorStatus = :status WHERE k.id = :id")intupdateVectorStatus(@Param("id")Longid,@Param("status")VectorStatusstatus);@Modifying@Query("DELETE FROM KnowledgeBaseEntity k WHERE k.id = :id")voiddeleteByIdCustom(@Param("id")Longid);
<!-- MyBatis 可以精确控制每一条 SQL --><selectid="complexSearch"resultType="User"> SELECT u.*, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.status = 'ACTIVE'
<iftest="name != null"> AND u.name LIKE #{name}
</if> GROUP BY u.id
HAVING COUNT(o.id) > #{minOrders}
ORDER BY order_count DESC
</select>
// 使用 PageablePage<User>page=userRepository.findAll(PageRequest.of(page,size,Sort.by("createTime").descending()));// 自定义分页查询@Query("SELECT k FROM KnowledgeBaseEntity k ORDER BY k.uploadedAt DESC")Page<KnowledgeBaseEntity>findAllOrderByUploadedAtDesc(Pageablepageable);// 返回分页信息publicPage<KnowledgeBaseDTO>getUsers(intpage,intsize){Pageablepageable=PageRequest.of(page,size);returnuserRepository.findAll(pageable).map(this::toDTO);}
// 问题:访问关联对象时触发额外查询@EntitypublicclassResumeAnalysisEntity{@ManyToOne(fetch=FetchType.LAZY)@JoinColumn(name="resume_id")privateResumeEntityresume;}// 解决:使用 @EntityGraph 或 JOIN FETCH@Query("SELECT a FROM ResumeAnalysisEntity a JOIN FETCH a.resume WHERE a.id = :id")Optional<ResumeAnalysisEntity>findByIdWithResume(@Param("id")Longid);
// 接口投影publicinterfaceUserNameOnly{StringgetName();StringgetEmail();}// 方法投影List<UserNameOnly>findUserNames();// DTO 投影@Query("SELECT new com.example.UserDTO(u.id, u.name) FROM User u")List<UserDTO>findAllUserDTO();
@RepositorypublicinterfaceKnowledgeRepositoryextendsJpaRepository<KnowledgeBaseEntity,Long>{// 方法名查询 - 按分类和上传时间查找List<KnowledgeBaseEntity>findByCategoryOrderByUploadedAtDesc(Stringcategory);// 方法名查询 - 统计状态数量longcountByVectorStatus(VectorStatusvectorStatus);// JPQL 查询 - 模糊搜索@Query("SELECT k FROM KnowledgeBaseEntity k WHERE LOWER(k.name) LIKE LOWER(CONCAT('%', :keyword, '%')) OR LOWER(k.originalFilename) LIKE LOWER(CONCAT('%', :keyword, '%')) ORDER BY k.uploadedAt DESC")List<KnowledgeBaseEntity>searchByKeyword(Stringkeywords);// 原生 SQL - 聚合统计@Query("SELECT COALESCE(SUM(k.accessCount), 0) FROM KnowledgeBaseEntity k")longsumAccessCount();}