4

OpenJPA 生成以下 where sql 部分

WHERE (t3.USERNAME = ? AND CAST(1 AS INTEGER) <> CAST(1 AS INTEGER) 
AND t5.USERNAME IS NOT NULL AND 1 = 1 AND 1 = 1 AND 1 = 1)

我刚刚加入了几张桌子,最后做到了

Join<SomeEntity, User> userJoin = someJoin.join(SomeEntity_.user);
Path<String> usernamePath = userJoin.get(User_.username);
CriteriaBuilder cb = getCb();
Predicate usernamePredicate = cb.equal(usernamePath, username);

JPA 发送到数据库的 sql 中奇怪的部分是

CAST(1 AS INTEGER) <> CAST(1 AS INTEGER)

这个表达式永远是错误的。所以永远不会有用户被选中。

好的,还有

1 = 1 AND 1 = 1 AND 1 = 1

表达式真的很奇怪,但是数据库的查询优化器应该删除它们,因为它们是真实的。

  1. 是否有人拥有由 OpenJPA 生成的相同或相似的奇怪 sql 语句?
  2. 谁能告诉我(希望是 OpenJPA 开发人员)为什么 OpenJPA 会生成如此奇怪的语句?

研究继续

今天在 OpenJPA 2.2.1 源码中找到了生成语句的地方。我截取了调试会话的屏幕截图并标记了有趣的地方。

放大1:http: //i.stack.imgur.com/LBmzM.png

在此处输入图像描述

4

1 回答 1

3

解决了

我终于在 OpenJPA 2.2.1 源代码中找到了导致生成这个奇怪语句的地方。

这个解释非常有趣,即使我的问题的原因位于我的代码中,因为我从来没有想过 OpenJPA 会创建这样的语句。

当您使用空的“in-values”集合创建 SQL in 表达式时,就会发生这种情况。例如:

Collection<String> usernames = .... // dynamically created 
                                    // (maybe by another query before)
Path<String> username = userJoin.get(User_.username);
Predicate usernamePredicate = username.in(usernames);

当用户名集合为空时,您将获得由 OpenJPA 生成的奇怪 SQL。好的,如果用户名集合为空,则 SQL-in 表达式将永远评估为 false。我认为 OpenJPA 开发人员希望通过生成一个在这种情况下评估为 false 的 SQL 表达式来简化数据库优化器的工作。因此他们将

 CAST(1 AS INTEGER) <> CAST(1 AS INTEGER) 

在 SQL 语句中。

到目前为止,我可以理解其目的是什么,但是为什么他们不能通过生成一个 SQL 来让我们开发人员的生活更轻松,让我们知道他们为什么生成总是错误的表达式。例如,如果它可以为人类提供有关正在发生的事情的信息(提示),则该声明可能会更加清晰。例如:

 WHERE 'user.username in(emptyCollection)' IS NOT NULL;

这也总是错误的,但开发人员可能会理解问题所在。

于 2013-06-26T07:05:58.007 回答