【问题标题】:JPA 2.0 IllegalArgumentException on existing entities and populated DB value现有实体和填充的数据库值上的 JPA 2.0 IllegalArgumentException
【发布时间】:2015-12-23 11:44:04
【问题描述】:

我正在尝试根据已填充表中的条件 ID (subid) 从表中返回一个字符串。查询应返回 ItemDataPoint 实体类型的列表。在 JSF 托管 bean 中,列表将通过增强的 for 循环进行迭代。如果循环找到“包含”一词,该方法将创建特定类型的图表。简单来说,我想根据满足的 ID 条件返回一个字符串。我得到:

javax.ejb.EJBException
at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException
(EJBContainerTransactionManager.java:748)
at com.sun.ejb.containers.EJBContainerTransactionManager.
completeNewTx(EJBContainerTransactionManager.java:698)
at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx
(EJBContainerTransactionManager.java:503)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4475)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2009)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1979)
Caused by: java.lang.IllegalArgumentException: You have attempted to set 
a parameter at position 2 which does not exist in this query string SELECT p FROM 
Itemdatapoint p JOIN p.series s WHERE s.master.item.subs.subid = :subid.
at org.eclipse.persistence.internal.jpa.QueryImpl.setParameterInternal(QueryImpl.java:925)
at org.eclipse.persistence.internal.jpa.QueryImpl.setParameterInternal(QueryImpl.java:906)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:469)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:1)
at com.manaar.clientmods.gazprom.design3.data.facade.ItemdatapointFacade.
chartType(ItemdatapointFacade.java:78)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

如果我在数据库中的相关父表上运行本机 SQL 查询,则存在 subid 值 2。 subid 的类型也是主实体类、JPQL Facade 类和托管 bean 中的 int。

JPQL:

public List<Itemdatapoint> chartType (int subid) {
    Query q = em.createQuery("SELECT p FROM Itemdatapoint p JOIN p.series s WHERE s.master.item.subs.subid = :subid");
    q.setParameter(subid, "subid");
    return q.getResultList();
}

托管 bean:

@Named(value = "reportBean")
@SessionScoped
public class ReportBean implements Serializable {

@Inject
private ItemdatapointFacade facade;

public String typeSwitch1() {
    subid = 2;
   chartType = facade.chartType(subid);
   for(Itemdatapoint e: chartType) {
       status = e.getSeries().getMaster().getStatus();
       if(status.equals("Include")) {
           return "line";
       }
   }
   return null; 
}

xhtml 页面:

<p:chart type="#{reportBean.typeSwitch1()}" model="#{reportBean.subLineChart1}"/>

我也尝试了一个非 Join JPQL 只是从一个表:

public List<Itemdatapoint> noJoin (int subid) {
    Query q = em.createQuery("SELECT p FROM Itemdatapoint p WHERE p.pointid = :subid");
    q.setParameter(subid, "subid");
    return q.getResultList();

}

类似的问题:

 java.lang.IllegalArgumentException: You have attempted to set a
 parameter at position 2 which does not exist in this query string 
 SELECT p FROM Itemdatapoint p WHERE p.pointid = :subid.

我收集到 IllegalArgumentException 意味着所选实体不存在或者不是与外观类中的查询字符串一致的正确类型。但在我的情况下,实体存在并且参数是正确的类型。

如果能帮助我理解为什么会出现此错误,我将不胜感激。提前致谢!

更新

响应lametaweb的回答,我想更好地理解JPA参数的概念。

根据 JPA 文档,setParameter 方法的第一个参数是参数名称或编号。第二个参数是应该绑定到命名参数的对象。为什么以下工作没有抛出 Illegal ArgumentException?

我测试了一个 xhtml(网页):

<p:dataGrid id="rep1" columns="1" value="#{pageBean.itemPageList1}"  var="items1" rows="4">
<p:commandLink value="#{items1.itemname}" action="#{pageBean.showItem1}" ajax="false"/>                                    
</p:dataGrid>

bean 代码:

  public ListDataModel<Sectionitem> getItemPageList1() {
    subid = 1;
    reportStatus = "Include";
    itemPageList1 = itemFacade.viewItems(subid, reportStatus);
    return itemPageList1;
}

JPA 门面:

public ListDataModel<Sectionitem> viewItems(int subid, String stat) {
    Query q = em.createQuery("select s from Sectionitem s JOIN s.subs c where c.subid = :subid AND s.status = :stat ORDER BY s.daterec");
 q.setParameter("subid", subid);
 q.setParameter("stat", stat);
    ListDataModel<Sectionitem> res
            = new ListDataModel<Sectionitem>(q.getResultList());
    return res;
}

为什么在这种情况下,对象存在但在我原来的情况下 subid 对象不存在?

【问题讨论】:

  • 如果答案解决了您的问题,请接受。要将答案标记为已接受,请单击答案旁边的复选标记以将其从空心切换为绿色。
  • 对不起,我不完全理解答案背后的概念,我很乐意尽快接受。请参阅我对问题的更新和对答案的 cmets。非常感谢
  • 我没有看到编辑。您必须发布包含“@lametaweb”字符串的评论,我才能知道编辑。好的。在您的原始答案中,您写道:q.setParameter(subid, "subid");,但在最后一个示例中,您写了q.setParameter("subid", subid);。前者是错误的,因为subid是参数VALUE而不是参数POSITION,后者是OK的。在后者中,您将 int 作为第二个参数传递,Java 使用自动装箱将其自动包装在 Integer 中。你可以看到所有这些重载方法here
  • 感谢所有有用的解释!现在说得通了。粗心大意,没有按照setParameter的顺序,先包含位置再包含值。

标签: jpa


【解决方案1】:

您正在代码中调用此方法:

setParameter(int position, Object value)

但您必须改为调用这个:

setParameter(String name, Object value)

所以你的代码应该是:

q.setParameter("subid", Integer.valueOf(subid));

但是,如果你调用:

q.setParameter(subid, "subid");

这里第一个参数代表参数的位置,第二个参数代表它的值。因此,您正在为第二 (2) 位置的参数传递一个“subid”值,该值不存在,因为您的 JPQL 查询中只有一个参数,因此出现 IllegalArgumentException 异常。

注意:为什么您的实体中有原始类型?为什么不是整数而不是整数?

【讨论】:

  • 602210 我遵循这个非常有用的答案的逻辑,但我想了解为什么在某些情况下参数对象存在,而它在我的原始案例中抛出 IAE,如问题更新中所要求的那样。在我的第二个测试用例中,我也只有一个 subid int 参数。那么为什么第一个案例抛出 IllegalArgumentException 而第二个测试案例有效呢?谢谢! ——
猜你喜欢
  • 2020-07-04
  • 2019-05-08
  • 1970-01-01
  • 2020-12-28
  • 2016-01-02
  • 2011-08-15
  • 2020-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多