我有一个名为“employee”的表,其中 id 作为列。我想通过提供 ids 列表来查询数据库,并仅获取数据库中不存在的 id。我试过了
@Query(value = "select id from (VALUES(:ids)) v(id) except (select id from employee)",
nativeQuery = true)
public List<String> filterNonExistingEmployeeiIds(@Param("ids") List<String> ids);
我尝试使用本机查询和值(:ids)进行传递。它只选择一个 id,而不是列表中所有传递的 id。有什么方法可以选择列表中的所有值。
我认为 Postgres 的 SQL 应该是这样的
select *
from unnest(array['id1','id2','id3', ...]) as t(id)
where id not in (select e.id from Employee as e);
我认为你不能用 JPA 或 HQL 编写这个(至少使用 Hibernate ORM 5),而且我不确定你是否可以使用参数。
但是,你可以尝试这个:
@Query(
value = "select * from unnest(array[:ids]) as t(id) where id not in (select id from Employee as e)",
native=true)
public List<String> filterNonExistingEmployeeiIds(@Param("ids") List<String> ids);
或者您可以创建一个表示 ids 列表的字符串和
string_to_array
:
@Query(
value="select * from unnest(string_to_array(:ids, ',')) as t(id) where id not in (select e.id from Employee as e)",
native=true)
public List<String> filterNonExistingEmployeeiIds(@Param("ids") String ids);
...
List<String> ids = ...
String idsAsString = ids.stream().collect(Collectors.joining(",");
List<String> nonExistingIds = repository.filterNonExistingEmployeeiIds(idsAsString);
如果这两种方法都不起作用,您可以自己创建查询字符串并使用自定义存储库:
public class CustomRepositoryImpl implements CustomRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<String> filterNonExistingEmployeeiIds(List<String> ids) {
String query = ... // create the query
return entityManager.createNativeQuery(query, String.class).getResultList();
}
}
它只选择一个 id,而不是列表中所有传递的 id。有什么方法可以选择列表中的所有值吗?
是的,它至少可以在反应式本机查询中工作
org.springframework.data.r2dbc.repository.Query
,但我相信它也可以在标准 JPA 中工作。
有两点:
(VALUES :ids)
而不是 (VALUES (:ids))
@Query("select * from (VALUES :ids) as v(id)...")
(VALUES (id1), (id2), (id3), ...)
,因此传递 Collection<Object[]> ids
而不是 Collection<String> ids
/** The internal implementation */
@Query("select * from (VALUES :ids) as v(id)...")
List<String> getMyValuesImpl(Collection<Object[]> ids);
/** The method with a nice signature */
default List<String> getMyValues(Collection<String> ids) {
return getMyValuesImpl(ids.stream().map(id -> new Object[]{id}).toList());
}