在纯JPA @Query中传递Enum值的方法有哪些?

时间:2018-10-08 07:30:12

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

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

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

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子句中指定键(例如主键),就无法更新或删除记录。

1 个答案:

答案 0 :(得分: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方法。