【问题标题】:Spring Data JPA and Exists querySpring Data JPA 和 Exists 查询
【发布时间】:2015-08-04 04:57:46
【问题描述】:

我正在使用 Spring Data JPA(将 Hibernate 作为我的 JPA 提供程序)并希望定义一个带有 HQL 查询的 exists 方法:

public interface MyEntityRepository extends CrudRepository<MyEntity, String> {

  @Query("select count(e) from MyEntity e where ...")
  public boolean existsIfBlaBla(@Param("id") String id);

}

当我运行这个查询时,我得到一个java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Boolean

HQL 查询必须看起来如何才能使其工作?我知道我可以简单地返回一个 Long 值,然后在 count &gt; 0 时检查我的 Java 代码,但这种解决方法应该不是必需的,对吧?

【问题讨论】:

  • 显然你可以改变你的 JPQL 查询以返回一个布尔值 ... 通过不返回 "count(e)" 而返回一个布尔表达式

标签: java hibernate jpa spring-data jpql


【解决方案1】:

Spring data 提供了使用字段检查行是否存在的方法: 示例:boolean existsByEmployeeIdAndEmployeeName(String employeeId, String employeeName);

【讨论】:

    【解决方案2】:

    这些天变得容易多了!

    @Repository
    public interface PageRepository extends JpaRepository<Page, UUID> {
    
        Boolean existsByName(String name); //Checks if there are any records by name
        Boolean existsBy(); // Checks if there are any records whatsoever
    
    }
    

    【讨论】:

      【解决方案3】:

      你可以像这样返回一个布尔值:

      import org.springframework.data.jpa.repository.Query;
      import org.springframework.data.jpa.repository.QueryHints;
      import org.springframework.data.repository.query.Param;
      
      @QueryHints(@QueryHint(name = org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE, value = "1"))
      @Query(value = "SELECT (1=1) FROM MyEntity WHERE ...... :id ....")
      Boolean existsIfBlaBla(@Param("id") String id);
      

      Boolean.TRUE.equals(existsIfBlaBla("0815")) 可能是一个解决方案

      【讨论】:

      • 没有按预期工作。返回null 值而不是false
      【解决方案4】:

      您可以在 jpaRepository 中使用 .exists(返回布尔值)。

      if(commercialRuleMsisdnRepo.exists(commercialRuleMsisdn.getRuleId())!=true){
      
              jsRespon.setStatusDescription("SUCCESS ADD TO DB");
          }else{
              jsRespon.setStatusCode("ID already exists is database");
          }
      

      【讨论】:

        【解决方案5】:

        您可以使用Case 表达式在您的选择查询中返回boolean,如下所示。

        @Query("SELECT CASE WHEN count(e) > 0 THEN true ELSE false END FROM MyEntity e where e.my_column = ?1")
        

        【讨论】:

        • 哪些? afaik 它总是会返回布尔值,不是吗?
        • 你尝试了哪些数据库?
        【解决方案6】:

        Spring Data JPA 1.11 现在支持存储库查询派生中的 exists 投影。

        请参阅文档here

        在您的情况下,以下将起作用:

        public interface MyEntityRepository extends CrudRepository<MyEntity, String> {  
            boolean existsByFoo(String foo);
        }
        

        【讨论】:

        • 如果你能添加一个工作示例,我很乐意投票。
        • 这就是 Spring 数据的全部意义——你不必编写任何 HQL :)
        • 是的,但是如果您想检查一个字段上是否存在具有值的记录 - 这绝对是一个简单的用例 :) 但对于更复杂的情况,我同意 - spring 数据有时效率不高。
        • 不起作用。 org.springframework.data.mapping.PropertyReferenceException: No property existsByXxx found for type Xxx!
        • @AnkitSoni 原来,Spring Data JPA 1.11 首先在 Spring Boot 1.5 中可用。
        【解决方案7】:

        除了公认的答案,我建议另一种选择。 使用QueryDSL,创建一个谓词并使用exists() 方法,该方法接受一个谓词并返回布尔值。

        QueryDSL 的一个优点是您可以将谓词用于复杂的 where 子句。

        【讨论】:

          【解决方案8】:

          自 Spring data 1.12 起,您可以通过扩展 QueryByExampleExecutor 接口(@98​​7654322@已经扩展它)来使用示例功能的查询。
          然后你可以使用这个查询(等等):

          <S extends T> boolean exists(Example<S> example);
          

          考虑一个实体MyEntity,它作为属性name,你想知道是否存在具有该名称的实体,忽略大小写,然后对该方法的调用可以如下所示:

          //The ExampleMatcher is immutable and can be static I think
          ExampleMatcher NAME_MATCHER = ExampleMatcher.matching()
                      .withMatcher("name", GenericPropertyMatchers.ignoreCase());
          Example<MyEntity> example = Example.<MyEntity>of(new MyEntity("example name"), NAME_MATCHER);
          boolean exists = myEntityRepository.exists(example);
          

          【讨论】:

          • 在我的情况下并不相关,因为我的查询是在 HQL 中
          【解决方案9】:

          在我的情况下,它不像以下那样工作

          @Query("select count(e)>0 from MyEntity e where ...")
          

          您可以将其作为布尔值返回

          @Query(value = "SELECT CASE  WHEN count(pl)> 0 THEN true ELSE false END FROM PostboxLabel pl ...")
          

          【讨论】:

            【解决方案10】:

            我认为您可以简单地更改查询以返回布尔值

            @Query("select count(e)>0 from MyEntity e where ...")
            

            PS: 如果根据主键值检查是否存在CrudRepository 已经有exists(id) 方法。

            【讨论】:

            • 感谢指向 exists(id) 的指针,但我的 where 子句包含一些复杂的约束...
            • count(e)&gt;e 可能仅适用于某些数据库(例如 Oracle)。使用 DB2 则不需要,您必须使用 select case when count(e) &gt; 0 then true else false end from Entity e
            • 在此处执行 SQL 存在查询,而不是计算行数。使用 count 必须完成索引中的所有行(希望如此),否则没有索引的表扫描。 SQL exists 将在第一个遇到的行之后返回,而不是像 count(*) 那样查找每一行并计算它们。在 10 行表中,这在 10s/100s 的情况下没有问题,甚至更多。
            • 基本上,检查计数比简单地检查它的存在要慢;在没有更好的解决方案的情况下,答案是可行的,但不是最理想的。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-09-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多