JPA在使用SELECT时的奇怪行为

huangapple go评论76阅读模式
英文:

JPA strange behavior when using SELECT

问题

我刚接触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")));

然而,这个命令返回了数据库中的9倍结果。例如,如果数据库有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")));

结果将与数据库中列出的内容相同。

这两段代码之间唯一的区别是,我没有直接将cq.from(...)传递给select(),而是传递了cq.from(...)的结果。

个人而言,我认为这两种编码方式之间没有任何区别,但结果却表明另一种情况。

有人可以花点时间解释一下吗?

英文:

I am new to Java and try developing a SWing app for library using JPA controller generated.

When I try to select result from sql server database, I use this command

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery&lt;BookTitles&gt; cq = criteriaBuilder.createQuery(BookTitles.class);
cq.select(cq.from(BookTitles.class)).where(criteriaBuilder.isNull(cq.from(BookTitles.class).get(&quot;status&quot;)));

This command, however, returns 9 times of rows in db. For example, if db has 10 rows, it will repeat this 10 rows around 9 times and return a list with 90 elements.

Instead of this code, I changed to

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery&lt;BookTitles&gt; cq = criteriaBuilder.createQuery(BookTitles.class);
Root&lt;BookTitles&gt; root = cq.from(BookTitles.class);
cq.select(root).where(criteriaBuilder.isNull(root.get(&quot;status&quot;)));

and the results will be the same as listed in db.

The only different between these two codes is that instead of passing cq.from(...) directly to select(), I pass result of cq.from(...).

Personally, I donot think there is any differences between these two ways of coding, but the results tell the other way.

Can someone take time to explain?

答案1

得分: 1

这不是奇怪的行为。

通过两次使用CriteriaBuilder方法,您正在为该子句设置两个表,用于进行笛卡尔积操作。

正如您在文档中所看到的:

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

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

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

英文:

It's not strange behavior

By using the CriteriaBuilder method twice, you are setting two tables in that clause for what the Cartesian product does.

As you can see in the documentation

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

"Create and add a query root corresponding to the given entity, forming a cartesian product with any existing roots."

So the correct way is the second one, storing the table that forms the from clause in a variable, and using this instead of adding more tables to the from clause with the criteriaquery from method.

huangapple
  • 本文由 发表于 2020年8月23日 23:46:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63548953.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定