有没有办法在 Spring Data @Query 注释值中使用常量?
Posted
技术标签:
【中文标题】有没有办法在 Spring Data @Query 注释值中使用常量?【英文标题】:Is there a way to use constants inside Spring Data @Query annotation value? 【发布时间】:2013-08-26 12:20:47 【问题描述】:我不想硬编码常量值,我宁愿通过引用变量来指定它们。
例如,而不是编写下一个查询:
@Query(value = "SELECT u FROM UserModel u WHERE u.status = 1")
..我想提取硬编码值 '1' 并编写如下内容:
@Query(value = "SELECT u FROM UserModel u WHERE u.status = UserModel.STATUS_ACTIVE") //doesn't compile
有没有办法像第二个例子那样在 spring-data 查询中指定常量?
【问题讨论】:
【参考方案1】:你必须像这样使用完全限定的类名:
@Query("SELECT u FROM UserModel u WHERE u.status = com.example.package.UserModel.STATUS_ACTIVE")
不过,它的坏处是 IDE 不会将其识别为对 UserModel 类的使用。唯一的好处是您可以将值保存在一个地方,这在大多数情况下就足够了。 这已在IntelliJ IDEA 2017.1 中解决。我不知道其他 IDE。
【讨论】:
这会引发“com 未定义”的异常 .. 至少对我而言 您是否为您的目的应用了完全限定的包名称?我的意思是你必须用它的完全限定名称指向正确的、现有的类。 是的,我做到了。我解决了传递枚举值进行比较的问题。不优雅,但工作 它适用于我,具有完全限定的名称,但正在比较的字段在实体中定义为@Enumerated(EnumType.STRING)
。【参考方案2】:
我建议在实体上创建一个 Enum
和该枚举的字段。
public enum UserModelStatus
ACTIVE, INACTIVE
public UserModel
/* Other fields ommitted */
@Enumerated(EnumType.STRING)
private UserModelStatus status;
/* Get/Set Method */
然后创建你的存储库方法:
@Repository
public interface UserModelRepository extends JpaRepository<UserModel, Long>
public List<UserModel> findByStatus(UserModelStatus status);
使用 Spring Data,您甚至不需要编写 JPQL,只需调用如下方法:
@Autowired
UserModelRepository userModelRepository;
public void someMethod()
List<UserModel> userModels = userModelRepository.findByStatus(UserModelStatus.ACTIVE);
【讨论】:
如何轻松否定 findByStatus(UserModelStatus 状态)?我的意思是获取 UserModelStatus 为 not 状态的所有 userModel? findByStatusNot(UserModelStatus 状态) 这显示了spring数据的全部威力。坚持简单查询,不用自己写sql。【参考方案3】:如下使用:
在repository界面,定义一个常量如下:
public static final String USER_QUERY = "SELECT u FROM UserModel u WHERE u.status = " + UserModel.STATUS_ACTIVE;
现在你可以使用
@Query(value=USER_QUERY)
【讨论】:
【参考方案4】:我已经设法通过 SpEL T() 运算符在查询中使用类 String 常量,这使您可以访问给定类的静态方法和常量。对于字符串,我必须用单引号 (') 包裹表达式,您可能也需要它(如果发生 QuerySyntaxException)。
试试这样的,
@Query("SELECT u FROM ##entityName u " +
"WHERE u.status = #T(fully.qualified.path.UserModel).STATUS_ACTIVE")
注意:如果您使用 UserModel 而不是 ##entityName,它会以某种方式不起作用。
在文档中简要提及,请参阅:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-beandef-xml-based
不知道什么时候支持,我有spring-data-jpa 1.4.3,spring-framework 3.2.17
【讨论】:
如果你想在原生查询中使用参数化语句,你可以使用SELECT columns FROM table_name WHERE column_name = ?#T(fully.qualified.path.ClassName).STATIC_CONSTANT_VARIABLE
(添加?
:?#T(...
)。我需要WHERE column_name NOT IN (?#T(namespace.ClassName).STRING_COLLECTION_VARIABLE)
,而没有?
,它没有被参数化,所以没有达到预期的效果。【参考方案5】:
对于标准解决方案,这个问题的答案似乎是“否”。
一些 JPA 实现可能有自己的解决方案,但休眠对于一个似乎不支持,也不支持此处其他答案建议的任何方法。
【讨论】:
【参考方案6】:当您想直接在 @Query 注释中使用常量时,您可以编写如下内容:
@Query("SELECT u FROM UserModel u WHERE u.status = " + UserModel.STATUS_ACTIVE)
【讨论】:
这将返回一个错误,指出属性值必须是常量。 我就是这么说的。这个答案是关于在 @Query 注释中使用常量。 是的,但是 CONSTANT + CONSTANT 不再是常数了:) 因此出现错误。 这对我有用。如果您需要一个字符串,请不要忘记在查询中将其用单引号'
括起来。
The value for annotation attribute Query.value must be a constant expression
【参考方案7】:
是的,这是一种更优雅的方式,而且它也易于阅读。例如:
@Query("SELECT xyz.id FROM XYZ AS xyz WHERE xyz.status = " + Status.OPEN + " AND xyz.active=1")
这里,Status
是一个包含静态常量的简单类:
public class Status
public static final int OPEN = 1;
【讨论】:
错了。您不能在这些表达式中放置常量。 Java 错误:The value for annotation attribute Query.value must be a constant expression
@gene b。这在我的项目中有效,我在这个 SO 答案中确实复制了它。我的 Spring 版本是 2.3.4,如果这很重要的话。我不是这样写这个例子的。以上是关于有没有办法在 Spring Data @Query 注释值中使用常量?的主要内容,如果未能解决你的问题,请参考以下文章
spring-data-jpa 存储库在 Query 中使用 Collection 作为 @Param
spring data jpa @Query 枚举类型不返回数据
Spring Data JPA 常用注解 @Query@NamedQuery