2012-05-23 48 views
0

我有一個JPA查詢數據庫的問題。有例外:如何構建查詢條件是對象的多個屬性的jpql查詢?

org.hibernate.QueryParameterException: Position beyond number of declared ordinal parameters. Remember that ordinal parameters are 1-based! Position: 1 
    at org.hibernate.engine.query.spi.ParameterMetadata.getOrdinalParameterDescriptor(ParameterMetadata.java:80) 
    at org.hibernate.engine.query.spi.ParameterMetadata.getOrdinalParameterExpectedType(ParameterMetadata.java:86) 
    at org.hibernate.internal.AbstractQueryImpl.determineType(AbstractQueryImpl.java:444) 
    at org.hibernate.internal.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:416) 
    at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:440) 
    at org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:67) 
    at com.lawa.service.impl.SubjectServiceImpl.getTotal(SubjectServiceImpl.java:746) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 

我的代碼是:

@Transactional(propagation=Propagation.REQUIRED) 
    public long getTotal(PSubject search) { 
     StringBuilder jsql = new StringBuilder("select count(*) from PSubject p where p.id=p.id "); 
     ArrayList paramValues = new ArrayList(); 
     if(search.getName()!=null && search.getName().trim().length()>0) { 
      jsql.append(" and p.name=:name"); 
      paramValues.add(search.getName().trim()); 
     } 
     if(search.getType()!=null && search.getType().trim().length()>0) { 
      jsql.append(" and p.type=:type"); 
      paramValues.add(search.getType().trim()); 
     } 
     if(search.getMacaddress()!=null && search.getMacaddress().trim().length()>0) { 
      jsql.append(" and p.macaddress=:macaddress"); 
      paramValues.add(search.getMacaddress().trim()); 
     } 
     if(search.getUri()!=null && search.getUri().trim().length()>0) { 
      jsql.append(" and p.uri=:uri"); 
      paramValues.add(search.getUri().trim()); 
     } 
     if(search.getDescription()!=null && search.getDescription().trim().length()>0) { 
      jsql.append(" and p.description=:description"); 
      paramValues.add(search.getDescription().trim()); 
     } 
     if(search.getCreateTime()!=null) { 
      jsql.append(" and p.createTime=:createTime"); 
     } 
     Query query = persistService.getEntityManager().createQuery(jsql.toString()); 
     for(int i=0;i<paramValues.size();i++) { 
      query.setParameter((i+1), paramValues.get(i)); 
     } 
     if(search.getCreateTime()!=null) { 
      query.setParameter(":createTime",search.getCreateTime(),TemporalType.DATE); 
     } 
     Long count = (Long)query.getSingleResult(); 
     return count; 
    } 

首先我想使代碼工作,我不喜歡的代碼。我覺得它不乾淨,我必須逐一驗證「PSubject」的每個屬性並聯系jpql,因爲它的類型是「Date」,所以我必須選擇「createTime」。更重要的是,我在jpql中添加了「p.id = p.id」,這讓我感覺不太好。

請幫我解決異常並給出最佳做法。

回答

1

如果使用命名參數,你應該名約束他們:

query.setParameter("macaddress", theMacAddress); 

所以,你應該寧可使用Map來保存您的參數值,由他們的名字索引。

但是這種動態查詢正是爲什麼設計了JPA標準API的原因。你應該使用它。

1

您應該使用Criteria而不是Query。 這對於這個用例來說非常完美。