我正在使用 Spring Data JPA (4.3.5) 存储库和使用 IN 关键字子句并以
List<Enum>
字段作为参数的查询方法。问题是它没有按我的预期工作。
给定一个像这样的实体:
@Entity
@Table(name = "R_REPRESENTACIO")
public class Representacio {
@Enumerated(EnumType.STRING)
private Estat estat;
...
//getters and setters
...
}
使用 SQL 声明:
CREATE TABLE R_REPRESENTACIO (
UUID NUMBER(19) NOT NULL,
...
ESTAT VARCHAR2(255) NULL,
...
);
Estat
是一个枚举类,例如:
public enum Estat {
VALIDA,
PENDENT_VALIDACIO,
PENDENT_DOCUMENTACIO,
...
}
还有一个 JPA 存储库,例如:
public interface RepresentacioRepository extends JpaRepository<Representacio, Long> {
List<Representacio> findAllByEstatIn(List<Estat> estats);
}
当我运行(集成测试类)时:
List<Estat> estats =
Arrays.asList(Estat.VALIDA,Estat.PENDENT_DOCUMENTACIO,Estat.PENDENT_VALIDACIO);
List<cat.aoc.representa.domain.entity.representacio.Representacio> allByEstatIn = representacioRepository.findAllByEstatIn(estats);
生成的 SQL 是(在内存 H2 DB 中):
2018-08-01 12:30:48.534--ServerSession(1175154004)--Connection(384887832)--Thread(Thread[main,5,main])--SELECT UUID, .... FROM R_REPRESENTACIO WHERE (ESTAT IN ((?,?,?)))
bind => [VALIDA, PENDENT_DOCUMENTACIO, PENDENT_VALIDACIO]
没有抛出 SQL 异常,返回零结果。 但这应该返回 1 个结果,因为(等效的)SQL 返回:
SELECT count(*) FROM R_REPRESENTACIO WHERE ESTAT IN ('VALIDA','PENDENT_DOCUMENTACIO','PENDENT_VALIDACIO');
COUNT(*)
----------
1
我能看到的独特区别是我如何将 IN 子句参数包装在 '' 之间(该列是 VARCHAR)。
我不知道为什么从 JPA 存储库生成的 SQL 没有返回结果。 (我也尝试过
findAllByEstatIsIn(List<Estat> estats)
,但返回了相同的零结果)。
有什么建议/解释吗?
PS:解决方法(不满意)使用
List<Representacio> findAllByEstatOrEstatOrEstat(Estat estat, Estat estat2, Estat estat3);
但这在很多方面都是丑陋且错误的......
使用 Spring Data JPA 和 JPQL 非常简单:
@Repository
public interface RepresentacioRepository extends JpaRepository<Representacio, Long> {
@Query("select r from Representacio r where r.estat in :estat2")
List<Representacio> findByEnumEstat(@Param("estat2") List<Estat> estatList);
}
我建议使用类型为
List<String>
的参数并添加转换器 String -> Enum
,以便 Spring 能够对其进行转换。所以,基本上:
List<Representacio> findByEstatIn(List<String> estats);
@Configuration
public class ConverterConfiguration extends RepositoryRestConfigurerAdapter {
@Autowired
private EstatsConverter estatsConverter;
@Override
public void configureConversionService(ConfigurableConversionService conversionService) {
conversionService.addConverter(estatsConverter);
super.configureConversionService(conversionService);
}
@Component
public class EstatsConverter implements Converter<String, Estat> {
@Override
public Estat convert(String source) {
return Estat.fromString(source);
}
}
我不知道这是否可行,但我记得做过类似的事情,只是在 MongoDB 中。如果你尝试的话请告诉我。
我也遇到这个问题了。我找到了here并希望将其写为答案。我希望,它可以节省某人宝贵的时间。
示例代码如下:
@Query(nativeQuery = true,
value = "SELECT * FROM articles
WHERE stage IN (:#{#stages.![name()]})")
List<Article> getByStageIn(@Param("stages") List<ArticleStage> stages);