OpenJPA生成奇怪的SQL语句

时间:2013-06-25 14:28:41

标签: java sql openjpa

OpenJPA生成以下sql part

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 会产生如此奇怪的陈述吗?
  3. 研究继续进行

    今天我在OpenJPA 2.2.1源代码中找到了生成语句的位置。 我拍了调试会话的截图并标出了有趣的地方。

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

    enter image description here

1 个答案:

答案 0 :(得分:3)

解决

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

即使我的问题的原因位于我的代码中,解释也是非常有趣的, 因为我从未想到OpenJPA会创建这样的声明。

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

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表达式将评估为 假。 我认为OpenJPA开发人员希望让数据库优化器的生命更轻松 通过生成在这种情况下将评估为false的SQL表达式。 因此他们放置了

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

在SQL语句中。

到目前为止,我可以理解它的目的是什么,但为什么它们不能成就 通过生成一个让我们知道它们生成原因的SQL,我们的开发人员也更容易 总是虚假的表达。 例如,如果它能够为人类提供有关正在发生的事情的信息(一个提示),那么该声明可以更加清晰。 例如:

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

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