JPA 2 查询返回不完整的结果

发布于 2024-09-28 15:53:55 字数 211 浏览 2 评论 0原文

以下查询仅匹配在 select 子查询中找到的第一个值,即使所有值都匹配 SELECT p FROM Profile p WHERE p.id IN (SELECT u.group FROM User u WHERE u.id = ? 1)

子查询返回一个逗号分隔的列表,如:1,2,3。该查询应返回所有三个子查询选择结果的匹配项。有人知道可能出了什么问题吗?谢谢。

The following query is only matching the first value found in the select subquery, even though there are match for all values SELECT p FROM Profile p WHERE p.id IN (SELECT u.group FROM User u WHERE u.id = ?1)

The subquery returns a comma separated list like: 1,2,3. The query should return matches for all three subquery select results. Anyone know what could be wrong? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我一向站在原地 2024-10-05 15:53:55

IN 子句在 JPQL 和 SQL 中都不能以这种方式工作。

(..) 中的值不是“逗号分隔的字符串”,而是一个值列表。该列表可以按字面指定为逗号分隔的字符串,也可以通过子查询生成,就像您的情况一样。也就是说,查询中的条件为 p.id IN ("1,2,3") (而不是 p.id IN (1,2,3) ),所以它不会产生期望的结果。

因此,您不能使用强大的查询语言(JPQL 或 SQL)来针对非规范化模式编写查询(您的列包含值列表,因此它违反了 1NF)。如果ProfileUser之间存在多对多关系,请将其表示为带有中间连接表的多对多关系。

IN clause doesn't work this way neither in JPQL nor SQL.

Value inside (..) is not a "comma separated string", it's a list of values. This list can be specified literally as a comma separated string, or it can be produced by subquery, as in your case. That is, condition in your query works as p.id IN ("1,2,3") (rather than p.id IN (1,2,3)), so it doesn't produce the desired result.

So, you can't use power of query languages (JPQL or SQL) to write queries against denormalized schema (your column contains a list of values, therefore it violates 1NF). If you have many-to-many relation between Profiles and Users, express it as many-to-many relation with intermediate join table.

无需解释 2024-10-05 15:53:55

虽然 IN 运算符支持与子查询的结果进行比较,但您所做的事情不起作用(而且我很惊讶您竟然得到了一个结果)。在进一步讨论之前,让我引用一下 JPA 2.0 规范:

4.6.9 在表达式中

使用的语法
比较运算符 [NOT] IN 中
条件表达式如下:

 in_表达式 ::=
    {状态字段路径表达式| type_discriminator} [NOT] IN
        {(in_item {,in_item}*)| (子查询)|集合值输入参数 }
in_item ::= 文字 |单值输入参数

state_field_path_expression
必须有字符串、数字、日期、
时间、时间戳或枚举值。

文字和/或输入参数
值必须相似相同
的抽象模式类型
类型中的state_field_path_expression。 (参见第 4.12 节)。

子查询的结果必须是
相同的抽象模式类型
state_field_path_expression 类型
。子查询在中讨论
第 4.6.16 节。

示例:

o.country IN('英国'、'美国'、'法国')
对于 UK 为 true,对于 Peru 为 false,
并且等价于表达式
(o.country = '英国') OR (o.country =
'美国')或(o.country = '法国')

o.country NOT IN ('英国', '美国',
'France')
对于 UK 为 false,对于 UK 为 true
对于秘鲁,相当于
表达式 NOT ((o.country = 'UK') OR
(o.country = '美国') OR (o.country =
'法国'))
.

其中必须至少有一个元素
定义的逗号分隔列表
IN 的值集
表达。

如果a的值
IN 或 NOT IN 表达式中的 state_field_path_expressionin_itemNULL 或未知,则
表达式的值未知。

请注意,使用集合值
输入参数意味着
静态查询无法预编译。

因此,首先,p.id 与子选择的返回类型不匹配(这实际上是一个“小”问题)。

其次,这是一个主要问题和误解,您的查询不会导致类似这样的结果(使用“伪代码”):

p.id IN (1, 2, 3) 

这是您想要的 - 但其中

p.id IN (’1,2,3’) 

显然不是您想要的,并且不会”不工作。

我唯一的建议:规范化你的数据库。

While the IN operator supports comparison against the results of a subquery, what you're doing can't work (and I'm surprised that you even get one result). Before going further, let me quote the JPA 2.0 specification:

4.6.9 In Expressions

The syntax for the use of the
comparison operator [NOT] IN in a
conditional expression is as follows:

 in_expression ::=
    {state_field_path_expression | type_discriminator} [NOT] IN
        { ( in_item {, in_item}* ) | (subquery) | collection_valued_input_parameter }
in_item ::= literal | single_valued_input_parameter 

The state_field_path_expression
must have a string, numeric, date,
time, timestamp, or enum value.

The literal and/or input parameter
values must be like the same
abstract schema type of the
state_field_path_expression in type. (See Section 4.12).

The results of the subquery must be
like the same abstract schema type of the
state_field_path_expression in type
. Subqueries are discussed in
Section 4.6.16.

Examples:

o.country IN (’UK’, ’US’, ’France’)
is true for UK and false for Peru,
and is equivalent to the expression
(o.country = ’UK’) OR (o.country =
’US’) OR (o.country = ’ France’)
.

o.country NOT IN (’UK’, ’US’,
’France’)
is false for UK and true
for Peru, and is equivalent to the
expression NOT ((o.country = ’UK’) OR
(o.country = ’US’) OR (o.country =
’France’))
.

There must be at least one element in
the comma separated list that defines
the set of values for the IN
expression.

If the value of a
state_field_path_expression or in_item in an IN or NOT IN expression is NULL or unknown, the
value of the expression is unknown.

Note that use of a collection-valued
input parameter will mean that a
static query cannot be precompiled.

So, first, p.id doesn't match the return type of the subselect (which is actually a "minor" issue).

Second, and this is a major issue and misunderstanding, your query won't result in something like this (using "pseudo code"):

p.id IN (1, 2, 3) 

which is what you'd like - but in

p.id IN (’1,2,3’) 

which obviously is not what you want, and won't work.

My only advice: normarlize your database.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文