我可以在 JpaRepository nativeQuery 中使用枚举参数吗?

Posted

技术标签:

【中文标题】我可以在 JpaRepository nativeQuery 中使用枚举参数吗?【英文标题】:Can I use enum parameter into JpaRepository nativeQuery? 【发布时间】:2017-11-11 15:00:17 【问题描述】:

实体看起来像这样:

@Getter
@Setter
@Entity
public class Application 
@Id
private Long id;
@Enumerated(EnumType.STRING)
private ApplicationStatus status;

代码是这样工作的:

public interface ApplicationRepository extends JpaRepository<Application, Long> 
@Query("SELECT app FROM ##entityName AS app WHERE app.status LIKE :status")
List<Application> find(@Param("status") ApplicationStatus status);

但是与 nativeQuery 相同的 sn-p - 没有:

@Query(value = "SELECT app.* FROM application AS app WHERE app.status LIKE :status", nativeQuery = true)
List<Application> findNative(@Param("status") ApplicationStatus status);

我没有任何例外,只是空列表。

我该如何解决这个问题? enum 可以和nativeQuery 一起使用吗?

P.S 我可以将 String 传递给方法而不是 ApplicationStatus 但也许还有其他选择?

【问题讨论】:

你有什么错误吗?用 nativeQuery 运行 sn-p 后,你得到了什么? Problems with making a query when using Enum in entity的可能重复 @the_bluescreen 我没有任何例外,只是空列表 在方法中使用 String 类型的 status 参数而不是枚举 ApplicationStatus 对我来说是一个很好的解决方案。 将值作为字符串传递是一种解决方法,但最好知道是否有更好的解决方案。如果是 JPA 查询,它似乎可以按预期工作,但如果是本机查询,则返回空结果 【参考方案1】:

以下similar question 具有类似要求,one of the answers 指向Spring Expression Language (SpEL),您可以使用:

public interface ApplicationRepository extends JpaRepository<Application, Long> 
    @Query(nativeQuery = true, value = "SELECT app FROM ##entityName AS app WHERE app.status=:##status.name()")
    List<Application> find(@Param("status") ApplicationStatus status);

上面重要的部分是app.status=:##status.name()

【讨论】:

【参考方案2】:

要扩展@Aivaras 的答案: 如果你想使用状态列表,SpEL 表达式略有不同——你需要做一个投影:

public interface ApplicationRepository extends JpaRepository<Application, Long> 
    @Query(nativeQuery = true, value = "SELECT app FROM ##entityName AS app WHERE app.status in :##statuses.![name()]")
    List<Application> find(@Param("statuses") List<ApplicationStatus> statuses);

注意表达式的变化

##statuses.![name()]

【讨论】:

如果你不介意,你能解释一下spEL如何用于收集的语法吗? @ArunGowda 它被称为集合投影docs.spring.io/spring-framework/docs/current/reference/html/…。所以我们从枚举集合中创建字符串集合【参考方案3】:

您可以在传递参数之前转换为字符串。

【讨论】:

正如我在上面写的“附言我可以将字符串传递给方法而不是 ApplicationStatus 但也许还有其他选择?”【参考方案4】:

在出现此错误几天后,我找到了解决方案。

我做了很多研究,并以多种方式测试了将@Param("environment") environment: Environment作为参数接收:

 :##environment.TESTING
 :##environment
 :##environment.name()
 CAST(:##environment.name() as environment)

Kotlin 中的解决方案

关键在查询中。 您必须使用.name() 将参数的值转换为字符串(或接收字符串作为参数)并将字符串类型的值转换为所需的特定枚举。因为直接在查询中传递 Enum 类型的对象是行不通的。

假设您的数据库中的 Enum 定义为 environment

@Query(
        value = "SELECT some_routine(CAST(:##environmentNamedParam.name() as environment))",
        nativeQuery = true
)
fun yourFunction(
        @Param("environmentNamedParam") environmentParam: Environment
) : Boolean

区分:

environmentNamedParam 环境参数 环境

#spring #jpa #postgresql #kotlin

【讨论】:

【参考方案5】:

我使用##paramName?.name()解决了这个问题

public interface ItemRepository extends JpaRepository<Item, Long> 
    @Query(value = "select * from items where type = :##type?.name()", nativeQuery = true)
    List<Item> findByType(@Param("type") EnumType type);

 
public enum EnumType  NORMAL, LARGE ;

【讨论】:

【参考方案6】:

这个怎么样?

public interface ApplicationRepository extends JpaRepository<Application, Long> 
List<Application> findByStatus(ApplicationStatus status);

【讨论】:

在我的问题中,我使用了简化示例,我的真实代码更复杂,我需要使用“nativeQuery”。

以上是关于我可以在 JpaRepository nativeQuery 中使用枚举参数吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何将对象从一个 JpaRepository 转换为另一个 JpaRepository

是否有 JpaRepository 方法可以在用户名条件下保存提供的密码?

是否可以使用 JpaRepository 在 Spring Data JPA 中使用“TRUNCATE”?还是比标准 deleteAll() 更有效的方法?

spring data jpa中实现JpaRepository接口的repository可以返回sortedset吗?

71 Spring 对于这部分 JpaRepository 的处理

71 Spring 对于这部分 JpaRepository 的处理