【问题标题】:Is there a way to use constants inside Spring Data @Query annotation value?有没有办法在 Spring Data @Query 注释值中使用常量?
【发布时间】: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 查询中指定常量?

【问题讨论】:

    标签: java spring jpql 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,如果这很重要的话。我不是这样写这个例子的。
        猜你喜欢
        • 1970-01-01
        • 2016-11-20
        • 1970-01-01
        • 1970-01-01
        • 2015-12-19
        • 2012-11-04
        • 2019-11-21
        • 1970-01-01
        • 2016-11-22
        相关资源
        最近更新 更多