【问题标题】:How to find distinct rows with field in list using JPA and Spring?如何使用 JPA 和 Spring 在列表中查找具有字段的不同行?
【发布时间】:2015-11-11 18:48:56
【问题描述】:

我正在使用 Spring 连接到数据库。我有一个扩展CrudRepository<People, Long> 的接口这是我想在数据库上执行的查询:SELECT DISTINCT name FROM people WHERE name NOT IN UserInputSet。我宁愿在没有任何 sql 注释的情况下这样做,所以如果没有NOT 是可能的,那很好。

有办法吗?我查看了 spring 文档,但我找不到任何东西 (http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation)


这是我累了,但它不起作用。

@Query("SELECT DISTINCT name FROM people WHERE name NOT IN (?1)")
List<String> findNonReferencedNames(List<String> names);

这是我得到的例外:

Error creating bean with name 'peopleRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List de.test.tasks.persistence.PeopleRepository.findNonReferencedNames(java.util.List)!

Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: people is not mapped [SELECT name FROM people WHERE name NOT IN (?1)]

【问题讨论】:

  • “它不工作”。再清楚不过了……除了发生了什么、什么错误、什么日志、什么实体等
  • 我会用我遇到的错误更新问题。
  • 你不应该“冒号”1 位吗?
  • 什么是实体“人”?应该有一个大写的“P”?
  • 这是一个原生查询。您应该将nativeQuery = true 作为参数添加到@Query

标签: java spring hibernate jpa java-8


【解决方案1】:

我终于能够找到一个没有@Query 注释的简单解决方案。

List<People> findDistinctByNameNotIn(List<String> names);

当然,我得到了 people 对象,而不仅仅是字符串。然后我可以在 java 中进行更改。

【讨论】:

  • 我也有类似的要求。我使用了List&lt;User&gt; findDistinctByUserName(),它在启动时抛出NoSuchElementException。但是,如果提供参数,它可以正常工作,但不会提供我想要的结果。参数是强制性的吗?如何获取不同列的整个表的值?
  • 这对你来说可能已经足够了,但我认为这不是对数据库进行预期的查询。这是获得不同的 People 实例,而不是 name 列的不同值。在您的示例中,这是在执行 SELECT DISTINCT * FROM people WHERE name NOT IN UserInputSet (通常不一样,除非 name 是主键)因此,根据所需的结果,您可能需要获取不同的名称你得到的人的名单。
  • 此外“我可以在 java 中进行更改” --- 你的意思是遍历人员列表并提取名称吗?如果您确实只是在寻找名称并且不关心People 上的其他值,那么效率会降低吗?与在 Java 中进行处理相比,使用 SQL 进行尽可能多的选择总是更好...
【解决方案2】:

您是否尝试过这样改写您的查询?

@Query("SELECT DISTINCT p.name FROM People p WHERE p.name NOT IN ?1")
List<String> findNonReferencedNames(List<String> names);

注意,我假设您的实体类名为 People,而不是 people

【讨论】:

    【解决方案3】:
    @Query("SELECT DISTINCT name FROM people WHERE name NOT IN (:names)")
    List<String> findNonReferencedNames(@Param("names") List<String> names);
    

    【讨论】:

    • 我认为您不需要在 :names 周围加上括号。
    【解决方案4】:
    @Query("SELECT distinct new com.model.referential.Asset(firefCode,firefDescription) FROM AssetClass ")
    List<AssetClass> findDistinctAsset();
    

    【讨论】:

    • 区分哪个字段?
    【解决方案5】:

    不能这样用吗?

    @Query("SELECT DISTINCT name FROM people p (nolock) WHERE p.name NOT IN (:myparam)")
    List<String> findNonReferencedNames(@Param("myparam")List<String> names);
    

    附:我经常在 SQL Server 2012 中编写查询,在服务器中使用 nolock 是一个好习惯,如果使用本地数据库,您可以忽略 nolock

    似乎您的数据库名称未正确映射(在您更新问题之后)

    【讨论】:

    • 命名参数的正确性不亚于位置(尽管我个人也会使用命名)。
    【解决方案6】:

    我认为这应该可以在不使用本机查询的情况下工作:

    List<Name> findDistinctByNameNotIn(List<String> names);
    
    interface Name{
        String getName();
    }
    

    并获取字符串使用:

    peopleRepository.findDistinctByNameNotIn().stream().filter(Objects::nonNu
    ll).map(PeopleRepository.Name::getName).collect(Collectors.toList())```
    

    【讨论】:

      【解决方案7】:

      您可以通过为每个列创建变量来创建另一个 bean 来获取数据,如下所示。

      @Getter
      @Setter
      @Builder
      @ToString
      public static class NameOnlyBean {
          //you have to follow camelCase here when creating variables.
          private String name;
      }
      

      并通过使用您的 JPA 查询使用创建的 bean 来获取数据列表。

      List<NameOnlyBean> yourJPAQuery(List<String> names);
      

      【讨论】:

        猜你喜欢
        • 2020-08-23
        • 1970-01-01
        • 2021-11-30
        • 1970-01-01
        • 2016-09-19
        • 2020-01-07
        • 1970-01-01
        • 1970-01-01
        • 2021-05-11
        相关资源
        最近更新 更多