【问题标题】:What are some ways to pass an Enum value in a pure JPA @Query?有哪些方法可以在纯 JPA @Query 中传递枚举值?
【发布时间】:2019-03-12 20:04:01
【问题描述】:

假设我想将记录的列值设置为“已解决”。但是,我希望从枚举中获取此值。因此,无论有人决定将“RESOLVED”更改为“RESOLVE”或类似的东西,查询都保持不变。换句话说,开发人员不需要使用新的 Enum 值编辑 JPA 查询。只是想知道有哪些方法可以解决,或者 JPA 是否不允许这样做。我知道查询是静态的,但早些时候我能够在查询中传递一个对象以将查询结果字段存储在其中。所以我想知道是否也可以对 Enums 做同样的事情。

这是我目前的策略:将“RESOLVE”作为@Param“状态”传递。但是,我仍然想知道如何传递 Enums,因为这感觉更像是一种解决方法,而不是回答问题本身。

public interface UpdateStatusStandardDAO extends JpaRepository<DBTableName, Long>
{

    @Transactional
    @Modifying(clearAutomatically = true)
    @Query("UPDATE"
            + " TableName tn"
            + " SET"
            + " tn.status =:status"
            + " WHERE"
            + " tn.field1 =:field1"
            + " AND tn.field2 =:field2"
            + " AND tn.field3 =:field3")
    int updateStatus(@Param("status") String status, @Param("field1") Long field1,
                     @Param("field2") String field2, @Param("field3") String field3);

}

我知道的: 1. @Transactional:用于更新/删除操作。否则,我得到 org.springframework.dao.InvalidDataAccessApiUsageException。 2.@Modifying(clearAutomatically = true):因为实体管理器默认不会自动刷新变化。

为简单起见,我们将 field1 视为主键。它的类型是 Long(也可以从接口签名中推断出来)。

对于纯粹的参考,如果 where 子句中的任何字段都不是键,那么如果设置了 SQL_SAFE_UPDATES 选项,则 SQL 工作台可能会拒绝您的查询。那是因为如果不在 where 子句中指定键(例如,主键),您将无法更新或删除记录。

【问题讨论】:

  • JPA 允许传入枚举作为参数,是的。您正在使用不是 JPA API 的“Spring Data JPA”(@Query 与 JPA API 无关)。您不发布您的实体,因此没有人知道例如“id”是什么类型。发布完整信息。一些 JDBC 驱动程序可能不允许在 UPDATE 子句中指定参数,但是在您实际发布尝试时发生的情况之前,没有太多要说的
  • 在此处发布您的实体类和枚举。
  • 这看起来不错,你有什么例外吗?
  • @SudhirOjha 将实体类和枚举放在这里。
  • @maslan 请参考问题更新,让我知道您的想法。

标签: java spring jpa enums spring-data-jpa


【解决方案1】:

这是不可能的,因为注解属性值必须是常量,而 Enum 不是常量。但是您可以使用 java8 接口默认方法作为解决它的技巧。模板代码:

public interface TheEntityJpaRepository extends JpaRepository<TheEntity, Long> {
  @Modifying(clearAutomatically = true)
  @Query("UPDATE TheEntity SET status = :status WHERE id = :value")
  int markToStatus(@Param("value") Long value, @Param("status") TheStatusEnum status);

  default int markAsResolved(Long value) {
    return markToStatus(value, TheStatusEnum.RESOLVED);
  }
}

@Entity
public class YourEntity {
  ...
  @Enumerated(EnumType.STRING)
  private Status status;
  ...
}

public enum TheStatusEnum {
  RESOLVED,
  ...
}

但你应该知道,这种方式会暴露markToStatus方法。

【讨论】:

  • 我不知道你可以在一个接口中拥有方法函数,比如“markAsResolved”。另外,请清除您将两个功能分开为一个可以设置的“marksToStatus”,也可以取消设置;另一个“标记为已解决”并将相关的枚举传递给它。该查询可以在其中包含自定义 POJO,因此我想如果开发人员添加了该功能以包含没有自身对象的枚举:stackoverflow.com/questions/2355728/…
  • 您提供的链接完全不是关于枚举,而是关于将选择行映射到 POJO。除此之外,JPA 原生支持枚举。
  • @RohanKumar 这就是 Java8 的特性,接口方法的默认实现
  • 是的,用于将选择行映射到 POJO。问起来似乎很业余,但 JPA 本身就支持 Enums?与此答案中提供的模板代码中的@Enumerated 用法一样吗?
  • @RohanKumar @Enumerated 注释类是 javax.persistence.Enumerated。这是一个 JPA api。所以我说 JPA 原生支持枚举。
猜你喜欢
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-06
  • 2018-01-19
  • 1970-01-01
相关资源
最近更新 更多