如何使用 JPA 和 Spring 在列表中查找具有字段的不同行?

Posted

技术标签:

【中文标题】如何使用 JPA 和 Spring 在列表中查找具有字段的不同行?【英文标题】:How to find distinct rows with field in list using JPA and 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 【参考方案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);

【讨论】:

以上是关于如何使用 JPA 和 Spring 在列表中查找具有字段的不同行?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring MVC (JPA) 中将实体对象列表转换为页面对象?

使用 Spring JPA 按名称查找多个对象

如何在本机查询中使用 NVL 或 COALESCE 获取 Spring Data JPA 中的值列表

如何添加到列表的链接以使用 spring-jpa 进行排序?

如何使用Spring数据jpa @Query注释直接获取学生列表

如何在JAVA JPA Spring Boot中的一个SQL查询中选择多个数据