如何使用 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<User> 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) 中将实体对象列表转换为页面对象?
如何在本机查询中使用 NVL 或 COALESCE 获取 Spring Data JPA 中的值列表
如何添加到列表的链接以使用 spring-jpa 进行排序?