我想在 PostgreSQL 13.2 的
where in
子句中使用 2 列。我通过执行以下查询来测试它
select * from collision_danger_pair_contexts
where
(first_target_id, second_target_id)
in
( ('63efc3d9-8fc7-4b39-a9ce-b926dae4e104', '63efc3d9-8fc7-4b39-a9ce-b926dae4e105') );
成功了。
现在的问题是如何使用 Spring Data JPA 实现相同的目的。我尝试过以下查询
@Query(
nativeQuery = true,
value = """
SELECT * FROM collision_danger_pair_contexts ctx
WHERE (ctx.first_target_id, ctx.second_target_id) IN (:targetIds)
"""
)
List<CollisionDangerPairContext> findByTarget1IdAndTarget2Id(@Param("targetIds") List<UUID[]> targetIds);
其中
targetIds
包含 UUID 数组的列表。每个数组的长度是2。
但是我遇到了错误:
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: record = bytea
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
在运行查询之前,我的直觉告诉我,我过于乐观地希望它能起作用,但我不明白应该如何以及在哪里进行“转换”。
我也尝试过将参数更改为
List<List<UUID>> targetIds
但它也不起作用。正确的语法/转换是什么?
对我来说最好的方法是使用
List<org.apache.commons.lang3.tuple.ImmutablePair<UUID, UUID>> targetIds
我会将 UUID 数组列表序列化为 2 维 JSON 数组,即
[
["63efc3d9-8fc7-4b39-a9ce-b926dae4e104", "63efc3d9-8fc7-4b39-a9ce-b926dae4e105"],
["63efc3d9-8fc7-4b39-a9ce-b926dae4e106", "63efc3d9-8fc7-4b39-a9ce-b926dae4e107"],
["63efc3d9-8fc7-4b39-a9ce-b926dae4e108", "63efc3d9-8fc7-4b39-a9ce-b926dae4e109"]
]
并将其作为参数传递给此本机查询:
select * from collision_danger_pair_contexts cdpc
where exists
(
select from json_array_elements((:targetIds)::json) j
where j ->> 0 = cdpc.first_target_id::text
and j ->> 1 = cdpc.second_target_id::text
);
使 SQL 元组查询发挥作用的一种方法是引入独立的托管实体或可嵌入实体并通过它们进行查询。
可嵌入实体示例:
/**
* This is to make tuple queries work with JPA, such as:
* <p>
* select *
* from entity e
* where (e.id1, e.id2) in (:pairsOfId);
*/
@Embeddable
@Getter
@Setter
public class EmbeddedRelation {
private UUID id1;
private UUID id2;
}
感兴趣的实体(
MyEntity
):
...
private RelatedEntity from;
private RelatedEntity to;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "id1", column = @Column(name = "from_id", insertable = false, updatable = false)),
@AttributeOverride(name = "id2", column = @Column(name = "to_id", insertable = false, updatable = false))
})
private EmbeddedRelation embeddedRelation;
JPA查询:
List<MyEntity> findByEmbeddedRelationIn(Collection<EmbeddedRelation> relations);