Mapping Entity Beans to Database Tables
abcolson May 31, 2004 2:04 AMGreetings,
I am using JBoss 3.2.3 with Postgres and encountering issues mapping beans/attributes to tables/fields. My table/field names sometimes have spaces and/or other characters that don't exactly match the bean, such as:
Mapping entity bean "Question" => Table "Questions"
Mapping entity bean "QuestionCategory" => Table "Question Categories"
Mapping entity bean getter getParentId() => Field "parent_id"
Here are my descriptors and stack trace when I try to access the "Questions" table:
ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar > <description><![CDATA[No Description.]]></description> <display-name>Generated by XDoclet</display-name> <enterprise-beans> <!-- Session Beans --> <session > <description><![CDATA[EJB that computes Fibonacci suite]]></description> <display-name>Fibo EJB</display-name> <ejb-name>Fibo</ejb-name> <home>tutorial.interfaces.FiboHome</home> <remote>tutorial.interfaces.Fibo</remote> <ejb-class>tutorial.ejb.FiboBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> <!-- To add session beans that you have deployment descriptor info for, add a file to your XDoclet merge directory called session-beans.xml that contains the <session></session> markup for those beans. --> <!-- Entity Beans --> <entity > <description><![CDATA[EJB that manages a Question]]></description> <display-name>Question EJB</display-name> <ejb-name>Question</ejb-name> <home>tutorial.interfaces.QuestionHome</home> <remote>tutorial.interfaces.Question</remote> <ejb-class>tutorial.ejb.QuestionBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>java.lang.Long</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>Questions</abstract-schema-name> <cmp-field > <description><![CDATA[]]></description> <field-name>id</field-name> </cmp-field> <cmp-field > <description><![CDATA[]]></description> <field-name>question</field-name> </cmp-field> <cmp-field > <description><![CDATA[]]></description> <field-name>categoryId</field-name> </cmp-field> <cmp-field > <description><![CDATA[]]></description> <field-name>level</field-name> </cmp-field> <primkey-field>id</primkey-field> <resource-ref > <res-ref-name>jdbc/PostgresDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> <query> <description><![CDATA[Lookup Question By ID]]></description> <query-method> <method-name>findByPrimaryKey</method-name> <method-params> <method-param>java.lang.Long</method-param> </method-params> </query-method> <result-type-mapping>Local</result-type-mapping> <ejb-ql><![CDATA[SELECT OBJECT(qb) FROM Questions qb WHERE qb.id = ?1]]></ejb-ql> </query> <!-- Write a file named ejb-finders-QuestionBean.xml if you want to define extra finders. --> </entity> <entity > <description><![CDATA[EJB that manages a Question Category]]></description> <display-name>Question Category EJB</display-name> <ejb-name>QuestionCategory</ejb-name> <home>tutorial.interfaces.QuestionCategoryHome</home> <remote>tutorial.interfaces.QuestionCategory</remote> <ejb-class>tutorial.ejb.QuestionCategoryBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>java.lang.Long</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>QuestionCategory</abstract-schema-name> <cmp-field > <description><![CDATA[]]></description> <field-name>id</field-name> </cmp-field> <cmp-field > <description><![CDATA[]]></description> <field-name>name</field-name> </cmp-field> <cmp-field > <description><![CDATA[]]></description> <field-name>parentId</field-name> </cmp-field> <primkey-field>id</primkey-field> <resource-ref > <res-ref-name>jdbc/PostgresDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> <query> <description><![CDATA[Lookup Question Category By ID]]></description> <query-method> <method-name>findByPrimaryKey</method-name> <method-params> <method-param>java.lang.Long</method-param> </method-params> </query-method> <result-type-mapping>Local</result-type-mapping> <ejb-ql><![CDATA[SELECT OBJECT(qcb) FROM QuestionCategoryBean qcb WHERE qcb.id = ?1]]></ejb-ql> </query> <!-- Write a file named ejb-finders-QuestionCategoryBean.xml if you want to define extra finders. --> </entity> <!-- To add entity beans that you have deployment descriptor info for, add a file to your XDoclet merge directory called entity-beans.xml that contains the <entity></entity> markup for those beans. --> <!-- Message Driven Beans --> <!-- To add message driven beans that you have deployment descriptor info for, add a file to your XDoclet merge directory called message-driven-beans.xml that contains the <message-driven></message-driven> markup for those beans. --> </enterprise-beans> <!-- Relationships --> <!-- Assembly Descriptor --> <assembly-descriptor > <!-- To add additional assembly descriptor info here, add a file to your XDoclet merge directory called assembly-descriptor.xml that contains the <assembly-descriptor></assembly-descriptor> markup. --> <!-- finder permissions --> <!-- finder permissions --> <!-- finder permissions --> <!-- transactions --> <!-- finder transactions --> </assembly-descriptor> </ejb-jar>
jbosscmp-jdbc.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jbosscmp-jdbc PUBLIC "-//JBoss//DTD JBOSSCMP-JDBC 3.0//EN" "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_0.dtd"> <jbosscmp-jdbc> <defaults> </defaults> <enterprise-beans> <!-- To add beans that you have deployment descriptor info for, add a file to your XDoclet merge directory called jbosscmp-jdbc-beans.xml that contains the <entity></entity> markup for those beans. --> <entity> <ejb-name>Question</ejb-name> <datasource>java:/PostgresDS</datasource> <datasource-mapping></datasource-mapping> <table-name>Questions</table-name> <cmp-field> <field-name>id</field-name> <column-name>id</column-name> </cmp-field> <cmp-field> <field-name>question</field-name> <column-name>question</column-name> </cmp-field> <cmp-field> <field-name>categoryId</field-name> <column-name>category_id</column-name> </cmp-field> <cmp-field> <field-name>level</field-name> <column-name>level</column-name> </cmp-field> </entity> <entity> <ejb-name>QuestionCategory</ejb-name> <table-name>Question Categories</table-name> <cmp-field> <field-name>id</field-name> <column-name>id</column-name> </cmp-field> <cmp-field> <field-name>name</field-name> <column-name>name</column-name> </cmp-field> <cmp-field> <field-name>parentId</field-name> <column-name>parent_id</column-name> </cmp-field> </entity> </enterprise-beans> </jbosscmp-jdbc>
jboss.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd"> <jboss> <enterprise-beans> <!-- To add beans that you have deployment descriptor info for, add a file to your XDoclet merge directory called jboss-beans.xml that contains the <session></session>, <entity></entity> and <message-driven></message-driven> markup for those beans. --> <entity> <ejb-name>Question</ejb-name> <jndi-name>ejb/tutorial/Question</jndi-name> <resource-ref> <res-ref-name>jdbc/PostgresDS</res-ref-name> <jndi-name>java:/PostgresDS</jndi-name> </resource-ref> </entity> <entity> <ejb-name>QuestionCategory</ejb-name> <jndi-name>ejb/tutorial/QuestionCategory</jndi-name> <resource-ref> <res-ref-name>jdbc/PostgresDS</res-ref-name> <jndi-name>java:/PostgresDS</jndi-name> </resource-ref> </entity> <session> <ejb-name>Fibo</ejb-name> <jndi-name>ejb/tutorial/Fibo</jndi-name> </session> </enterprise-beans> <resource-managers> </resource-managers> </jboss>
Stacktrace:
Find failed: java.sql.SQLException: ERROR: Relation "question" does not exist javax.ejb.FinderException: Find failed: java.sql.SQLException: ERROR: Relation "question" does not exist at org.jboss.ejb.plugins.cmp.jdbc.JDBCAbstractQueryCommand.execute(JDBCAbstractQueryCommand.java:238) at org.jboss.ejb.plugins.cmp.jdbc.JDBCAbstractQueryCommand.execute(JDBCAbstractQueryCommand.java:111) at org.jboss.ejb.plugins.cmp.jdbc.JDBCFindByPrimaryKeyQuery.execute(JDBCFindByPrimaryKeyQuery.java:108) at org.jboss.ejb.plugins.cmp.jdbc.JDBCFindEntityCommand.execute(JDBCFindEntityCommand.java:49) at org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager.findEntity(JDBCStoreManager.java:571) at org.jboss.ejb.plugins.CMPPersistenceManager.findEntity(CMPPersistenceManager.java:299) at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.findEntity(CachedConnectionInterceptor.java:300) at org.jboss.ejb.EntityContainer.find(EntityContainer.java:697) 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:324) at org.jboss.ejb.EntityContainer$ContainerInterceptor.invokeHome(EntityContainer.java:1043) at org.jboss.ejb.plugins.AbstractInterceptor.invokeHome(AbstractInterceptor.java:88) at org.jboss.ejb.plugins.EntitySynchronizationInterceptor.invokeHome(EntitySynchronizationInterceptor.java:197) at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invokeHome(CachedConnectionInterceptor.java:214) at org.jboss.ejb.plugins.AbstractInterceptor.invokeHome(AbstractInterceptor.java:88) at org.jboss.ejb.plugins.EntityInstanceInterceptor.invokeHome(EntityInstanceInterceptor.java:89) at org.jboss.ejb.plugins.EntityLockInterceptor.invokeHome(EntityLockInterceptor.java:61) at org.jboss.ejb.plugins.EntityCreationInterceptor.invokeHome(EntityCreationInterceptor.java:28) at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:88) at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267) at org.jboss.ejb.plugins.TxInterceptorCMT.invokeHome(TxInterceptorCMT.java:98) at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:92) at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:120) at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invokeHome(ProxyFactoryFinderInterceptor.java:93) at org.jboss.ejb.EntityContainer.internalInvokeHome(EntityContainer.java:483) at org.jboss.ejb.Container.invoke(Container.java:720) 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:324) at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284) at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:546) at org.jboss.invocation.local.LocalInvoker.invoke(LocalInvoker.java:101) at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:90) at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:46) at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:45) at org.jboss.proxy.ejb.HomeInterceptor.invoke(HomeInterceptor.java:173) at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:85) at $Proxy43.findByPrimaryKey(Unknown Source) at tutorial.web.ComputeServlet.doPost(ComputeServlet.java:107) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.jboss.web.tomcat.security.JBossSecurityMgrRealm.invoke(JBossSecurityMgrRealm.java:220) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.valves.CertificatesValve.invoke(CertificatesValve.java:246) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.jboss.web.tomcat.tc4.statistics.ContainerStatsValve.invoke(ContainerStatsValve.java:76) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2417) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:65) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:577) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:197) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:781) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:549) at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:605) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:677) at java.lang.Thread.run(Thread.java:534)