首页 > 解决方案 > 使用 SELECT 时的 JPA 奇怪行为

问题描述

我是 Java 新手,并尝试使用生成的 JPA 控制器为库开发 SWing 应用程序。

当我尝试从 sql server 数据库中选择结果时,我使用此命令

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<BookTitles> cq = criteriaBuilder.createQuery(BookTitles.class);
cq.select(cq.from(BookTitles.class)).where(criteriaBuilder.isNull(cq.from(BookTitles.class).get("status")));

但是,此命令在 db 中返回 9 次行。例如,如果 db 有 10 行,它将重复这 10 行大约 9 次,并返回一个包含 90 个元素的列表。

而不是这段代码,我改为

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<BookTitles> cq = criteriaBuilder.createQuery(BookTitles.class);
Root<BookTitles> root = cq.from(BookTitles.class);
cq.select(root).where(criteriaBuilder.isNull(root.get("status")));

结果将与 db 中列出的相同。

这两个代码之间的唯一区别是,我不是cq.from(...)直接传递给select(),而是传递cq.from(...).

就个人而言,我认为这两种编码方式之间没有任何区别,但结果表明相反。

有人可以花时间解释吗?

标签: javajpa

解决方案


这不是奇怪的行为

通过两次使用 CriteriaBuilder 方法,您将在该子句中设置两个表,用于笛卡尔积的作用。

正如您在文档中看到的

https://docs.oracle.com/javaee/7/api/javax/persistence/criteria/AbstractQuery.html#from-java.lang.Class-

“创建并添加与给定实体对应的查询根,形成具有任何现有根的笛卡尔积。”

所以正确的方法是第二种,将构成from子句的表存储在一个变量中,并使用它而不是使用criteriaquery from方法向from子句添加更多表。


推荐阅读