EntityQuery fails on getResultCount with composite primary keys on Oracle
typhoon1978 Jul 7, 2009 3:45 PMHi my friends, I'm trying to interact with an Oracle enterprise database through Seam, but I'm encountering lot of problems.
My development platform is based on Eclipse 3.4.2 / JBoss Tools / Seam 2.1.0-GA / JBoss AS 5.1.0-GA.
I try to explain the problem in detail, giving you all the components.
Here it is the table definition:
create table WV_DWH.WV0514A_FILIALE ( SQ_FILIALE_ID NUMBER not null, DT_REFERENCE DATE not null, CD_FILIALE VARCHAR2(100) not null, DS_FILIALE VARCHAR2(400), SQ_RDT_ID NUMBER not null, CD_CAB VARCHAR2(6), CD_ABI VARCHAR2(5), SQ_BANCA_ID NUMBER ) alter table WV_DWH.WV0514A_FILIALE add constraint WV0514A_PK primary key (DT_REFERENCE, SQ_FILIALE_ID) using index tablespace WVU_STAGE_INDX_S0 pctfree 10 initrans 2 maxtrans 255 storage ( initial 128K next 128K minextents 1 maxextents unlimited pctincrease 0 );
So we have a table with a composite primary key made up by a REFERENCE DATE and an ID.
The Seam Generate Entities
Eclipse mapping function creates two entity classes made up by an @Embeddable class (the ID) in which we have declared:
- Date dtReference
- BigDecimal sqFilialeId
and the table class in which we have declared:
- Wv0514aFilialeId id
- String cdFiliale
- String dsFiliale
- BigDecimal sqRdtId
- String cdCab
- String cdAbi
- BigDecimal sqBancaId
Here the classes definition:
package it.cogmps.massivesim.entity; // Generated 6-lug-2009 15.46.51 by Hibernate Tools 3.2.4.GA import java.math.BigDecimal; import java.util.Date; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.hibernate.validator.NotNull; /** * Wv0514aFilialeId generated by hbm2java */ @Embeddable public class Wv0514aFilialeId implements java.io.Serializable { private static final long serialVersionUID = -1437555899840893475L; private Date dtReference; private BigDecimal sqFilialeId; public Wv0514aFilialeId() { } public Wv0514aFilialeId(Date dtReference, BigDecimal sqFilialeId) { this.dtReference = dtReference; this.sqFilialeId = sqFilialeId; } @Temporal(TemporalType.DATE) @Column(name = "DT_REFERENCE", nullable = false, length = 7) @NotNull public Date getDtReference() { return this.dtReference; } public void setDtReference(Date dtReference) { this.dtReference = dtReference; } @Column(name = "SQ_FILIALE_ID", nullable = false, precision = 22, scale = 0) @NotNull public BigDecimal getSqFilialeId() { return this.sqFilialeId; } public void setSqFilialeId(BigDecimal sqFilialeId) { this.sqFilialeId = sqFilialeId; } public boolean equals(Object other) { if ((this == other)) return true; if ((other == null)) return false; if (!(other instanceof Wv0514aFilialeId)) return false; Wv0514aFilialeId castOther = (Wv0514aFilialeId) other; return ((this.getDtReference() == castOther.getDtReference()) || (this .getDtReference() != null && castOther.getDtReference() != null && this.getDtReference() .equals(castOther.getDtReference()))) && ((this.getSqFilialeId() == castOther.getSqFilialeId()) || (this .getSqFilialeId() != null && castOther.getSqFilialeId() != null && this .getSqFilialeId().equals(castOther.getSqFilialeId()))); } public int hashCode() { int result = 17; result = 37 * result + (getDtReference() == null ? 0 : this.getDtReference() .hashCode()); result = 37 * result + (getSqFilialeId() == null ? 0 : this.getSqFilialeId() .hashCode()); return result; } }
package it.cogmps.massivesim.entity; // Generated 6-lug-2009 15.46.51 by Hibernate Tools 3.2.4.GA import java.math.BigDecimal; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Table; import org.hibernate.validator.Length; import org.hibernate.validator.NotNull; /** * Wv0514aFiliale generated by hbm2java */ @Entity @Table(name = "WV0514A_FILIALE", schema="WV_DWH") public class Wv0514aFiliale implements java.io.Serializable { private static final long serialVersionUID = 349405820102500746L; private Wv0514aFilialeId id; private String cdFiliale; private String dsFiliale; private BigDecimal sqRdtId; private String cdCab; private String cdAbi; private BigDecimal sqBancaId; public Wv0514aFiliale() { } public Wv0514aFiliale(Wv0514aFilialeId id, String cdFiliale, BigDecimal sqRdtId) { this.id = id; this.cdFiliale = cdFiliale; this.sqRdtId = sqRdtId; } public Wv0514aFiliale(Wv0514aFilialeId id, String cdFiliale, String dsFiliale, BigDecimal sqRdtId, String cdCab, String cdAbi, BigDecimal sqBancaId) { this.id = id; this.cdFiliale = cdFiliale; this.dsFiliale = dsFiliale; this.sqRdtId = sqRdtId; this.cdCab = cdCab; this.cdAbi = cdAbi; this.sqBancaId = sqBancaId; } @EmbeddedId @AttributeOverrides( { @AttributeOverride(name = "dtReference", column = @Column(name = "DT_REFERENCE", nullable = false, length = 7)), @AttributeOverride(name = "sqFilialeId", column = @Column(name = "SQ_FILIALE_ID", nullable = false, precision = 22, scale = 0)) }) @NotNull public Wv0514aFilialeId getId() { return this.id; } public void setId(Wv0514aFilialeId id) { this.id = id; } @Column(name = "CD_FILIALE", nullable = false, length = 100) @NotNull @Length(max = 100) public String getCdFiliale() { return this.cdFiliale; } public void setCdFiliale(String cdFiliale) { this.cdFiliale = cdFiliale; } @Column(name = "DS_FILIALE", length = 400) @Length(max = 400) public String getDsFiliale() { return this.dsFiliale; } public void setDsFiliale(String dsFiliale) { this.dsFiliale = dsFiliale; } @Column(name = "SQ_RDT_ID", nullable = false, precision = 22, scale = 0) @NotNull public BigDecimal getSqRdtId() { return this.sqRdtId; } public void setSqRdtId(BigDecimal sqRdtId) { this.sqRdtId = sqRdtId; } @Column(name = "CD_CAB", length = 6) @Length(max = 6) public String getCdCab() { return this.cdCab; } public void setCdCab(String cdCab) { this.cdCab = cdCab; } @Column(name = "CD_ABI", length = 5) @Length(max = 5) public String getCdAbi() { return this.cdAbi; } public void setCdAbi(String cdAbi) { this.cdAbi = cdAbi; } @Column(name = "SQ_BANCA_ID", precision = 22, scale = 0) public BigDecimal getSqBancaId() { return this.sqBancaId; } public void setSqBancaId(BigDecimal sqBancaId) { this.sqBancaId = sqBancaId; } }
The seam generator creates also a wonderful UI to interact with the database. So now I'm ready to deploy the project to JBoss and browse my data through the UI, but it's here that I encounter the first problems...
The data browsing is perfect for the tables without a composite primary key, but not for the objects described above...
I saw the SQL queries in standard output written by
<property name="hibernate.show_sql" value="true"/>
setting in the persistence.xml configuration file.
I noticed that it tryies to make pagination through a couple of queries:
15:11:01,604 INFO [STDOUT] Hibernate: select * from ( select wv0514afil0_.DT_REFERENCE as DT1_50_, wv0514afil0_.SQ_FILIALE_ID as SQ2_50_, wv0514afil0_.CD_ABI as CD3_50_, wv0514afil0_.CD_CAB as CD4_50_, wv0514afil0_.CD_FILIALE as CD5_50_, wv0514afil0_.DS_FILIALE as DS6_50_, wv0514afil0_.SQ_BANCA_ID as SQ7_50_, wv0514afil0_.SQ_RDT_ID as SQ8_50_ from WV_DWH.WV0514A_FILIALE wv0514afil0_ ) where rownum <= ?
15:11:01,792 INFO [STDOUT] Hibernate: select * from ( select count((wv0514afil0_.DT_REFERENCE, wv0514afil0_.SQ_FILIALE_ID)) as col_0_0_ from WV_DWH.WV0514A_FILIALE wv0514afil0_ ) where rownum <= ?
I think that in the second query it's trying to count how many distinct primary objects are there, but the query is wrong...
The
count((wv0514afil0_.DT_REFERENCE, wv0514afil0_.SQ_FILIALE_ID))
statement has a bad syntax and so I've got the exception...
15:11:01,885 WARN [JDBCExceptionReporter] SQL Error: 907, SQLState: 42000 15:11:01,885 ERROR [JDBCExceptionReporter] ORA-00907: missing right parenthesis
Here it is the full stack trace:
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614) at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:128) at org.jboss.seam.framework.EntityQuery.initResultCount(EntityQuery.java:135) at org.jboss.seam.framework.EntityQuery.getResultCount(EntityQuery.java:126) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.jboss.seam.util.Reflections.invoke(Reflections.java:22) at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56) at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.transaction.TransactionInterceptor$1.work(TransactionInterceptor.java:97) at org.jboss.seam.util.Work.workInTransaction(Work.java:47) at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:91) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107) at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185) at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103) at it.cogmps.massivesim.session.Wv0514aFilialeList_$$_javassist_seam_3.getResultCount(Wv0514aFilialeList_$$_javassist_seam_3.java) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at javax.el.BeanELResolver.getValue(BeanELResolver.java:62) at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:54) at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72) at org.jboss.el.parser.AstPropertySuffix.getValue(AstPropertySuffix.java:53) at org.jboss.el.parser.AstValue.getValue(AstValue.java:67) at org.jboss.el.parser.AstChoice.getValue(AstChoice.java:29) at org.jboss.el.parser.AstChoice.getValue(AstChoice.java:29) at org.jboss.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186) at com.sun.facelets.el.ELText$ELTextVariable.writeText(ELText.java:184) at com.sun.facelets.el.ELText$ELTextComposite.writeText(ELText.java:108) at com.sun.facelets.compiler.TextInstruction.write(TextInstruction.java:45) ... 58 more Caused by: org.hibernate.exception.SQLGrammarException: could not execute query at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.loader.Loader.doList(Loader.java:2231) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125) at org.hibernate.loader.Loader.list(Loader.java:2120) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401) at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361) at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:88) ... 94 more Caused by: java.sql.SQLException: ORA-00907: missing right parenthesis at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:145) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745) at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:216) at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:922) at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1122) at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:973) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1244) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3469) at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3514) at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:342) at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208) at org.hibernate.loader.Loader.getResultSet(Loader.java:1808) at org.hibernate.loader.Loader.doQuery(Loader.java:697) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259) at org.hibernate.loader.Loader.doList(Loader.java:2228) ... 102 more
Please help me,
Thanks in advance.
Alex