【问题标题】:Issue with a JPA queryJPA 查询问题
【发布时间】:2010-04-24 15:07:23
【问题描述】:

我正在尝试执行以下 JPA 查询:

    public static final String UPDATE_INVENTORY_CUSTOMER_FOR_AMS_MAPPING = "UPDATE Inventory inventory SET" 
    + " inventory.customer.id = :" + DataAccessConstants.PARAM_CUSTOMER_ID
    + " ,inventory.lastUpdateUserId = :" + DataAccessConstants.PARAM_USER_ID
    + " where inventory.amsConsignorName = :" + DataAccessConstants.PARAM_AMS_CONSIGNOR_NAME
    + " and inventory.amsConsignorOrgCd = :" + DataAccessConstants.PARAM_AMS_CONSIGNOR_ORG_CD
    + " and inventory.amsConsignorTypeName = :" + DataAccessConstants.PARAM_AMS_CONSIGNOR_TYPE
    + " and inventory.status.code in (:" + DataAccessConstants.PARAM_STATUS + ")";  

但它看到以下内容:

update ATL_INVENTORY,  set CONSIGNOR_ID=?, LAST_UPDATE_USER_ID=? where AMS_CONSIGNOR_NAME=? and AMS_CONSIGNOR_ORG_CD=? and AMS_CONSIGNOR_TYPE_NAME=? and (CODE in (? , ? , ? , ?))

关于为什么表名后面有逗号的任何理想?


解决方案

我不得不将原始查询更改为以下内容:

update Inventory inv set " 
    + "inv.customer.id = :" + DataAccessConstants.PARAM_CUSTOMER_ID + " "
    + "where inv.amsConsignorName =:" + DataAccessConstants.PARAM_AMS_CONSIGNOR_NAME + " "
    + "and inv.amsConsignorOrgCd =:" + DataAccessConstants.PARAM_AMS_CONSIGNOR_ORG_CD + " "
    + "and inv.amsConsignorTypeName =:" + DataAccessConstants.PARAM_AMS_CONSIGNOR_TYPE + " "
    + "and exists(select 1 from Code code where inv.status = code and code.code in (:" + DataAccessConstants.PARAM_STATUS + "))

然后产生了这个:

update ATL_INVENTORY set CONSIGNOR_ID=? where AMS_CONSIGNOR_NAME=? and AMS_CONSIGNOR_ORG_CD=? and AMS_CONSIGNOR_TYPE_NAME=? and (exists (select 1 from ATL_CODE code1_ where ATL_INVENTORY.STATUS=CODE_ID and (code1_.CODE in (? , ? , ? , ?))))

基于此处的说明:Incorrect SQL generated for JPA QL Update statement involving multiple entities

【问题讨论】:

标签: java hibernate orm jpa


【解决方案1】:

您的查询代码为 UPDATE Inventory inventory SET,但生成的 SQL 显示为 update ATL_INVENTORY, set。为什么文字 SQL 字符串不是您编码的?当我遇到这样的谜团时,它们通常是由于假设一件事正在完成,而实际上另一件事正在发生。

这表明您编写的 SQL 并未按照您假设的方式用于生成该 SQL。看看这个查询可能来自哪里。我敢打赌,真正的来源中有一个放错位置的逗号。

您使用的是哪种 JPA 实现?如果我对错误的假设不正确,则说明实现中存在错误。你以前用过吗? UPDATE 成功了吗?如果是的话,它肯定被埋在你的代码库中的某个地方。

你有一个接口,里面有一堆常量。就个人而言,我不喜欢这样的设计。这是anti-pattern with a name

【讨论】:

  • 谢谢 - 关于“你有一个包含一堆常量的接口”这个问题是不正确的。只是一个带有静态命名查询的简单类。
  • 我也不太喜欢。为什么不将常量放在使用它们的类中?
  • 有人建议,如果您有很多命名查询,请将它们分别放在常量文件中。 pojo 然后只是引用它们。这种方式有常量,没有拼写错误的机会,我认为它更干净。
  • 我不同意。问题不是常数;这是我不喜欢的“单独”部分。如果您编写需要常量的 DAO,请务必将它们封装在 DAO 代码中。为什么要把它们放在别的地方?如果它们是使用它们的类中的静态最终常量,它们甚至可以是私有的。
  • 您是否考虑过使用@NamedQueries 代替常量?当您的持久性提供程序启动时,它们会被评估和缓存。将这些查询保存在它们所属实体的源文件中也是 imo 的好习惯。
【解决方案2】:

在我看来,JPA 提供程序中的错误不太可能发生,因此,正如@duffymo 所说,您确定您使用的是正确的常量,代码或依赖项可能是最新的吗?我会朝那个方向挖掘。

话虽如此,我真的很想知道您为什么不在 Java 代码中或在元数据映射文件(有趣的部分是人们没有发现在 EJB 2.x 中将 EJB-QL 查询外部化为 XML 非常易于管理,因此 JPA 的 @NamedQuery 注释)。

【讨论】:

  • 如前所述,我们正在使用@NameQuery。碰巧我已将命名查询放在同一个包中的单独文件中。我们有一个数据服务层,它允许我们将这些名称查询传递给数据层。对命名查询使用常量可以防止业务层开发人员在访问查询时遇到任何问题。
猜你喜欢
  • 1970-01-01
  • 2014-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
  • 2011-02-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多