JPA派生查询硬编码枚举字段值失败,求确认查询规则
问题描述
我定义了如下实体:
public class Alert extends { @Column(name = "STATUS_CDE", nullable = false, length = 1) @Convert(converter = AlertStatusCodeTypeConverter.class) private AlertStatusCodeType statusCde; }
statusCde是一个枚举字段:
public enum AlertStatusCodeType { INACTIVE("I"), ACTIVE("A"); private String code; AlertStatusCodeType(String c) { this.code = c; } }
数据库存读时,转换器负责将单字符String与枚举相互转换:
@Converter(autoApply = true) public class AlertStatusCodeTypeConverter implements AttributeConverter<AlertStatusCodeType, String> { // 将枚举转换为存入数据库的值 @Override public String convertToDatabaseColumn(AlertStatusCodeType alertStatusCodeType) { // 实现逻辑略 } // 将数据库中的值转换为枚举 @Override public AlertStatusCodeType convertToEntityAttribute(String code) { // 实现逻辑略 } }
我想编写JPA派生查询,筛选出ID在指定列表且状态为ACTIVE的Alert数据。如下查询方法可以正常工作:
List<Alert> findAllByIdInAndStatusCde(List<Long> ids, AlertStatusCodeType statusCode);
但我希望无需传入状态参数(直接筛选状态为'A'的数据),尝试编写如下方法时执行失败:
findAllByIdInAndStatusCdeActive(List<String> numbers)
报错信息:
No property active found for type AlertStatusCodeType! Traversed path: Alert.statusCde.
尝试CdeIsActive形式也无法成功。查阅Spring Data JPA文档后发现,仅isTrue这类isXXX关键词适用于布尔字段,请问是否确实如此?
解决方案
是的,Spring Data JPA的派生查询关键词中,isTrue/isFalse这类isXXX形式的关键词仅针对布尔类型字段,无法直接用于枚举类型来指定具体的枚举常量。针对你的需求,有两种简单可行的方案:
方案1:使用@Query注解编写JPQL查询
直接在查询方法上通过JPQL指定枚举常量,无需传入参数:
import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; public interface AlertRepository extends CrudRepository<Alert, Long> { @Query("SELECT a FROM Alert a WHERE a.id IN :ids AND a.statusCde = com.yourpackage.AlertStatusCodeType.ACTIVE") List<Alert> findAllByIdInAndActiveStatus(List<Long> ids); }
注意替换com.yourpackage为你实际的枚举所在包路径。
方案2:编写默认方法调用原有查询
利用接口默认方法,封装原有查询并自动传入ACTIVE枚举值:
public interface AlertRepository extends CrudRepository<Alert, Long> { List<Alert> findAllByIdInAndStatusCde(List<Long> ids, AlertStatusCodeType statusCode); default List<Alert> findAllByIdInAndActiveStatus(List<Long> ids) { return findAllByIdInAndStatusCde(ids, AlertStatusCodeType.ACTIVE); } }
这两种方案都能实现你无需手动传入状态参数、直接筛选ACTIVE状态数据的需求,其中方案2更简洁且复用了原有查询逻辑。
内容的提问来源于stack exchange,提问作者rhbc73
相关产品推荐
相关产品推荐

