Note that there are some explanatory texts on larger screens.

plurals
  1. POCan one-to-one shared primary key mapping in Hibernate be optional/null?
    text
    copied!<p>I have seen quite a few examples/tutorials on the web for doing one-one shared primary key mapping using Hibernate annotations. However in all the examples that I have seen it seems the mapping can't be optional or if it is optional it can't be on the primary key. I have the following situation where I have a one-one primary key mapping between a Company table and a CompanyDocs table. The CompanyDocs table is a weak entity, i.e although a Company object exists, it necessarily won't have a CompanyDocs entity linked from the start, however this may be created later on.</p> <p>The Company object are created and persisted by an external application, however updated using the Hibernate application. This is what I have..(Please note this is not the actual example)</p> <pre><code>Company table - companyid (Pk) - name - desc - test1 - test2 CompanyDocs table - docsid (Pk) (Fk) - detail1 - detail2 - detail3 </code></pre> <p>Model Classes</p> <pre><code>Company.java @Entity @Table(name = "company", schema = "public") public class Company implements java.io.Serializable { private String companyid private CompanyDocs companydocs; @Id @Column(name = "companyid", unique = true, nullable = false, length = 20) public String getCompanyid() { return this.companyid; } public void setCompanyid(String companyid) { this.companyid = companyid; } @OneToOne(fetch = FetchType.LAZY, mappedBy = "companydocs") @NotFound(action = NotFoundAction.IGNORE) @PrimaryKeyJoinColumn(name = "companyid", referencedColumnName = "docsid") public CompanyDocs getCompanydocs() { return this.companydocs; } public void setCompanydocs(CompanyDocs companydocs) { this.companydocs = companydocs; } </code></pre> <p>}</p> <pre><code>CompanyDocs.java @Entity @Table(name = "companydocs", schema = "public") public class CompanyDocs implements java.io.Serializable { private String docsid; private Company company; @GenericGenerator(name = "generator", strategy = "foreign", parameters = @Parameter(name = "property", value = "company")) @Id @GeneratedValue(generator = "generator") @Column(name = "docsid", unique = true, nullable = false, length = 20) public String getDocsid() { return this.docsid; } public void setDocsid(String docsid) { this.docsid = docsid; } @PrimaryKeyJoinColumn(name = "docsid", referencedColumnName = "companyid") @OneToOne(fetch = FetchType.LAZY) @NotFound(action = NotFoundAction.IGNORE) public Company getCompany() { return this.company; } public void setCompany(Company company) { this.company = company; } </code></pre> <p>CompanyDAOImpl.java</p> <pre><code>public Company getCompany(String companyid) { Criteria c = sessionFactory.getCurrentSession().createCriteria(Company.class) .add(Restrictions.eq("companyid", companyid)); try { return (Company) c.list().get(0); } catch(IndexOutOfBoundsException e) { logger.info("GetCompany threw exception " +e); return null; } } public void storeCompany(Company c) { sessionFactory.getCurrentSession().saveOrUpdate(c); } public void storeCompanyDocs(CompanyDocs cd) { sessionFactory.getCurrentSession().saveOrUpdate(cd); } public CompanyDocs getCompanyDocs(String companyid) { try{ Criteria c = sessionFactory.getCurrentSession() .createCriteria(CompanyDocs.class).add(Restrictions.eq("companyid", companyid)); logger.info("getCompanyDocsreturned"+c.list().get(0)); return (CompanyDocs)c.list().get(0); }catch(IndexOutOfBoundsException e){ logger.info("getCompanyDocs threw exception " +e); return null; } } </code></pre> <p>CompanyServiceImpl.java</p> <pre><code> @Transactional(propagation = Propagation.REQUIRED, readOnly= false, noRollbackFor=IllegalArgumentException.class) @ExceptionHandler(NullPointerException.class) public CompanyResponse updateCompany(Service parameters) throws SOAPException { LOG.info("In updateCompany"); Company c = companyDao.getCompany(parameters.getId()); //CompanyDocs cd = companyDao.getCompanyDocs(parameters.getId()); CompanyDocs cd = c.getCompanyDocs(); LOG.info("CompanyDocs object is:- " + cd); if(cd == null) { cd = new CompanyDocs(parameters.getId()); c.setCompanyDocs(cd); cd.setCompany(c); LOG.info("CompanyDocs object created new :- " + cd); companyDao.storeCompanyDocs(cd); LOG.info("CompanyDocs object stored :- " + cd.getDocsid()); } c.setDetail1(); c.setDetail2(); c.setDetail3(); ............. companyDao.storeCompany(c) LOG.info("Stored Company"); LOG.info("CompanyService Response Return------:") return new CompanyResponse(); } </code></pre> <p>My log file prints this.</p> <pre><code> 2012-05-02 22:57:18,951 INFO [au.com.CompanyServiceImpl] - &lt;In updateCompany&gt; 2012-05-02 22:57:18,975 INFO [au.com.CompanyDAOImpl] - &lt;getCompany returned au.com.Company@2738ef1d&gt;[au.com.CompanyServiceImpl] - &lt;CompanyDocs object is:- null&gt; 2012-05-02 22:57:18,991 INFO [au.com.CompanyServiceImpl] - &lt;CompanyDocs object created new :- au.com.CompanyDocs@373ee92&gt; 2012-05-02 22:57:18,995 INFO [au.com.CompanyServiceImpl] - &lt;CompanyDocs object updated :- CO12345&gt; 2012-05-02 22:57:19,338 INFO [au.com.CompanyDAOImpl] - &lt;Stored Company &gt; 2012-05-02 22:57:19,338 INFO [au.com.CompanyServiceImpl] - &lt;CompanyService Response Return------:&gt; 2012-05-02 22:57:19,498 ERROR [org.hibernate.jdbc.AbstractBatcher] - &lt;Exception executing batch: &gt; org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61) at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46) at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:68) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168) at org.hibernate.event.def.AbstractFlushingEventListener .performExecutions(AbstractFlushingEventListener.java:298) at org.hibernate.event.def.DefaultFlushEventListener. onFlush(DefaultFlushEventListener.java:27) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) at org.springframework.orm.hibernate3.HibernateTransactionManager. doCommit(HibernateTransactionManager.java:656) at org.springframework.transaction.support.AbstractPlatformTransactionManager. processCommit(AbstractPlatformTransactionManager.java:754) at org.springframework.transaction.support.AbstractPlatformTransactionManager .commit(AbstractPlatformTransactionManager.java:723) at org.springframework.transaction.interceptor.TransactionAspectSupport .commitTransactionAfterReturning(TransactionAspectSupport.java:393) at org.springframework.transaction.interceptor.TransactionInterceptor .invoke(TransactionInterceptor.java:120) at org.springframework.aop.framework.ReflectiveMethodInvocation .proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy. invoke(JdkDynamicAopProxy.java:202) at $Proxy28.login(Unknown Source) 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.apache.cxf.service.invoker.AbstractInvoker. performInvocation(AbstractInvoker.java:173) at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:89) at org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:60) at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:75) at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1. run(ServiceInvokerInterceptor.java:58) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at org.apache.cxf.workqueue.SynchronousExecutor. execute(SynchronousExecutor.java:37) at org.apache.cxf.interceptor.ServiceInvokerInterceptor. handleMessage(ServiceInvokerInterceptor.java:106) at org.apache.cxf.phase.PhaseInterceptorChain. doIntercept(PhaseInterceptorChain.java:255) at org.apache.cxf.transport.ChainInitiationObserver. onMessage(ChainInitiationObserver.java:113) at org.apache.cxf.transport.servlet.ServletDestination. invoke(ServletDestination.java:97) at org.apache.cxf.transport.servlet.ServletController. invokeDestination(ServletController.java:461) at org.apache.cxf.transport.servlet.ServletController. invoke(ServletController.java:188) at org.apache.cxf.transport.servlet.AbstractCXFServlet. invoke(AbstractCXFServlet.java:148) at org.apache.cxf.transport.servlet.AbstractHTTPServlet. handleRequest(AbstractHTTPServlet.java:179) at org.apache.cxf.transport.servlet. AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:103) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) at org.apache.cxf.transport.servlet.AbstractHTTPServlet. service(AbstractHTTPServlet.java:159) at org.apache.catalina.core.ApplicationFilterChain. internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain. doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve. invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve. invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve. invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler. process(Http11Protocol.java:588) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:662) 2012-05-02 22:57:19,501 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] - &lt;Could not synchronize database state with session&gt; </code></pre> <p>I have tried using @non annotation,optional = false/true, also tried using a uni-directional mapping and loading the companydocs object using criteria. But it seems Hibernate always excepts a CompanyDocs object for an existing Company..</p> <p>Strangely enough, this is used to work fine, when we were working with an earlier version of hibernate and were using mapping files , instead of annotaions. It was a shared key mapping but unidirectional so the Company hbm file had no mapping of CompanyDocs object. I am using hibernate 3.3.1.GA.jar for annotations. Is there something I have done wrong on my side or is this not possible anymore with the new version of Hibernate?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload