2012-05-03 5 views
2

私は、Hibernateアノテーションを使って1対1の共有主キーマッピングを行うためのWeb上でかなりの数のサンプル/チュートリアルを見てきました。しかし、私が見たすべての例では、マッピングはオプションではないようです。あるいは、オプションであれば、プライマリキーにはできません。私は、Companyテーブル とCompanyDocsテーブルの間に1対1の主キーマッピングを持つ次のような状況があります。 CompanyDocsテーブルは弱いエンティティです。つまり、Companyオブジェクトは存在しますが、必ずしもCompanyDocsエンティティが最初からリンクされているわけではありませんが、後で作成されることがあります。Hibernateでの1対1の共有プライマリキーマッピングはオプション/ nullにできますか?

Companyオブジェクトは外部アプリケーションによって作成され永続化されますが、Hibernateアプリケーションを使用して更新されます。 この私が持っているもの..です(これは実際の例ではありませんのでご注意ください)

Company table 
- companyid (Pk) 
- name 
- desc 
- test1 
- test2 

CompanyDocs table 
- docsid (Pk) (Fk) 
- detail1 
- detail2 
- detail3 

モデル・クラス

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; 
} 

}

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; 
    } 

CompanyDAOImpl.java

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;    
    } 

} 

Compan yServiceImpl.java

@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(); 

} 

ログファイルがこれを出力します。私はまた、単方向マッピングを使用してCOMPANYDOCSをロードしようとした、真/偽=オプション、@nonアノテーションを使用して試みた

2012-05-02 22:57:18,951 INFO [au.com.CompanyServiceImpl] - <In updateCompany> 
    2012-05-02 22:57:18,975 INFO [au.com.CompanyDAOImpl] - <getCompany returned   
    [email protected]>[au.com.CompanyServiceImpl] - <CompanyDocs object is:- null> 
    2012-05-02 22:57:18,991 INFO [au.com.CompanyServiceImpl] - <CompanyDocs object 
    created new :- [email protected]> 
    2012-05-02 22:57:18,995 INFO [au.com.CompanyServiceImpl] - <CompanyDocs object 
    updated :- CO12345> 
    2012-05-02 22:57:19,338 INFO [au.com.CompanyDAOImpl] - <Stored Company > 
    2012-05-02 22:57:19,338 INFO [au.com.CompanyServiceImpl] - <CompanyService 
    Response Return------:> 
    2012-05-02 22:57:19,498 ERROR [org.hibernate.jdbc.AbstractBatcher] - <Exception  
    executing batch: > 
    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]  
    - <Could not synchronize database state with session> 

は基準を使用してオブジェクト。しかし、Hibernateは常に既存の会社のCompanyDocsオブジェクトを除いているようです。

これは、以前のバージョンのhibernateで作業していて、annotionsの代わりにマッピングファイルを使用していたときにうまく機能するために使用されます。それは共有キーマッピングでしたが、一方向であったため、Company hbmファイルにはCompanyDocsオブジェクトのマッピングがありませんでした。 注釈のために私はhibernate 3.3.1.GA.jarを使用しています。私の側で間違っていたことはありますか、これはHibernateの新しいバージョンではもう不可能ですか?

答えて

1

companydocsオブジェクトの挿入コマンドではなく、Hibernateがアップデートを発行していたという問題がありました。これは、オブジェクトのプライマリキーがnullの場合、Hibernateは挿入を行い、nullでなければ更新を行い、以下のように実装クラスのキーを設定していたため、更新を行っていたからです。

オリジナルコード

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());  
    } 

新しいコード美しく勤務

if(cd == null) 
    { 
    cd = new CompanyDocs();//no-arg constructor 
    c.setCompanyDocs(cd); 
    cd.setCompany(c); 
    LOG.info("CompanyDocs object created new :- " + cd); 
    companyDao.storeCompanyDocs(cd); 
    LOG.info("CompanyDocs object stored :- " + cd.getDocsid());  
    } 

!!

タイプミスが問題であった申し訳ありませんが、私は

Hibernate StaleStateException

1

@PrimaryKeyJoinColumnは、オプションのサイドでのみ使用する必要があります。Companyに注釈が付いている@PrimaryKeyJoinColumnを削除してください。

さらに、@OneToOnemappedBy属性は、@OneToOneがマークされているエンティティのプロパティ名を参照する必要があります。

@OneToOne(fetch = FetchType.LAZY, mappedBy = "company") 
+0

この問題を修正するために、このリンクは有用であることが判明、mappedby属性が会社でした。また、私は会社側の@PrimaryKeyJoinColumnを削除しましたが、それは問題ではありませんでした。しかし、私は最終的に問題を解決しました、私の答えを見てください。 – Angela

+0

は、「@PrimaryKeyJoinColumnはオプションのサイドでのみ使用する必要があります」と記載されています。 OneToOneのマッピングにもいくつか問題があります。 – Cris

+0

こんにちはCris、それは私の控除と観測からです。その名前が示すように、 '@ PrimaryKeyJoinColumn'は、現在のテーブルのPKが別のテーブルへのFK制約を持つことを示します。したがって、別のテーブルにレコードが存在しない場合は、現在のテーブルのレコードのPKに使用できる値がないため、現在のテーブルにレコードを作成することはできません。したがって、現在の表はオプションの側です –

関連する問題