【发布时间】: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