JPQL中的实体比较在WHERE子句中如何工作?

8

在JPQL中,实体比较(相等性)语句是通过标识比较还是equals()方法比较,或者其他方式比较的?

我花了几个小时在谷歌和阅读Hibernate和JPA规范上搜索,但仍然找不到它是如何工作的。考虑以下实体:

class MyProductType{Integer id;}
class MyProduct{Integer id; MyProductType pType;}

现在是JPQL/HQL查询:

SELECT t FROM MyProductType t, MyProduct p WHERE p.pType = t

(我知道这是一个丑陋的查询语句,只要关注where从句的语义就可以了。)

那么 p.pType = t 是如何评估的呢?

JSR 317提到了“entity_expression”比较,但它的行为尚未明确。

编辑:我不喜欢Rika在下面的建议,因为.id方法包含了隐式内连接,而通常在查询中使用外部(左)连接时不需要这样做。


那个查询起作用了吗?我问这个问题的原因是通常人们会看到 p.pType.id = t.id 或者类似的语句。因为你仍然在从数据库查询,而数据库本身并不是对象。 - Rika
2
这只是一个简化的查询示例。我的实际情况要复杂得多。但是,它确实可以使用实体比较来工作。问题是它是如何工作的(JPA是否像您描述的那样进行ID比较,还是在实体上使用equals()方法)。我试图弄清楚的是,我是否可以依赖简短的语法,还是必须像您建议的那样执行完整的ID语句。 - sierre
2个回答

6
我在http://www.objectdb.com/java/jpa/query/jpql/comparison上发现了这个非常有趣的好问题。用户定义的类实例(实体类和嵌入式类)可以使用等号运算符(=,< >,==,!=)进行比较。对于实体类,如果e1和e2具有相同的类型和相同的主键值,则e1 = e2。对于嵌入式对象,如果e1和e2具有完全相同的内容,则e1 = e2。因此,似乎它会检查对象的主键值和对象的类型。所以,似乎使用p.pType = t时,它将检查(假设id是主键)p.pType的id与t的id是否相等。然后它将检查两个实体是否为相同类型或MyProductType。

2
我也发现了这个问题。但是它只适用于ObjectDB而不是JPA通用。感谢您的评论。 通过使用Hibernate进行一些调试,我发现实体比较转换为JPQL中的.id比较所对应的SQL完全相同。因此,如果在几天内没有其他答案,我想我会将您的答案标记为已接受。 - sierre

0

我在NetBeans环境中使用EclipseLink和MySQL DB也做了同样的事情。生成的SQL语句可以处理外键(在拥有对其他类对象引用的类的表格中)以及被引用对象的主键值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接