【问题标题】:JPQL select from multiple tablesJPQL 从多个表中选择
【发布时间】:2013-12-02 12:57:39
【问题描述】:

我是 JPQL 的新手,我认为这可能是一个非常简单的查询。如果以下可能,请有人解释一下。

我有两个不相关表:“customers”和“merchants”。它们都包含一个名为“用户名”的字段。是否有一个查询会返回一个“用户名”记录,该记录出现在任一表中并且与我提供的值匹配?

Query query = entityManager.createQuery("select c from Customers c where c.username = :username");                 
query.setParameter("username", username_);

类似这样的东西,但对于两个表。

【问题讨论】:

标签: select jpa jpql


【解决方案1】:

听起来您想将给定的用户名与CustomerMerchant 匹配。由于这两个表不相关,因此要使用单个查询来执行此操作,我相信您需要形成一个 cartesian product (将一个表的每一行与另一个表的每一行连接起来)。正如您可能想象的那样,这可能非常低效。你最好做两个简单的查询:

try {
  Customer c = em.createQuery("SELECT c FROM Customer c WHERE c.username = :username", Customer.class)
                 .setParameter("username", username)
                 .getSingleResult();

  // ... do something with the customer ...
} catch (NoResultException e) {
  // user wasn't found in the customer table, try merchant:
  try {
    Merchant m = em.createQuery("SELECT m FROM Merchant m WHERE m.username = :username", Merchant.class)
                   .setParameter("username", username)
                   .getSingleResult();

    // ... do something with the merchant ...
  } catch (NoResultException e) {
    // user wasn't found in either table
  }
}

注意:我假设usernameCustomerMerchant 中是唯一的。

请注意,如果我们没有找到第一个用户,这种方法只会执行第二个查询。如果您不需要返回对象(即只需要检查它是否存在),那么您可以通过两个计数查询来简化上述操作。计数查询始终返回结果,因此您无需捕获 NoResultExceptions

【讨论】:

  • 我只想补充一点,如果是我,遇到这样的情况会引发危险信号,也许我应该重新考虑设计。例如,为什么CustomerMerchant 不都扩展一个公共的User 类?如果有,您只需查询User
  • 感谢您的回答。我实际上有一个非常相似的解决方案,我只是想知道在 JPQL 中是否有更简洁的方法。关于扩展一个公共类,我对如何减少所需的 JPQL 代码量感到困惑。你是说我可以将所有用户表映射到User 类,然后运行类似:select u from User where u.username = :username
  • @Caiman 是的,假设CustomerMerchant 用户,您可以将用户名等常用内容移至User 超类。您仍然会有 CustomerMerchant 包含它们的任何特定属性。我没有完整的图片,所以可能会证明这不是一个好的改变……这只是一个想法。查看tutorial 了解更多信息。
【解决方案2】:

如果这真的不起作用:(我认为它确实如此,至少对于 CriteriaQuery 我确信它确实如此) Query query = entityManager.createQuery("select c from Customers c, Merchants m where c.username = :username 和 m.username = c.username");
query.setParameter("username", username_);

您总是可以这样做: Query query = entityManager.createQuery("select c from Customers c where c.username = :username 和 c.username in (select m.username from Merchants m)");
query.setParameter("username", username_);

【讨论】:

  • 感谢您的回答并为我的延迟回复道歉。不过,我可以从您的解决方案中看出我没有很好地解释我的问题,所以我再试一次。我想检查我的输入是否与客户 商家匹配 - 即,如果客户表中存在具有正确用户名的记录,则返回该记录。如果没有,则检查商家表,如果那里也没有匹配,则不返回任何内容。我希望这更清楚。
猜你喜欢
  • 2011-04-03
  • 2013-06-20
  • 2012-09-07
  • 2012-05-06
  • 2011-12-21
  • 2017-11-17
  • 2019-03-05
  • 1970-01-01
  • 2021-09-05
相关资源
最近更新 更多