2011-02-03 3 views
37

私は既存のDBスキーマを持つレガシーコードベースで作業しています。既存のコードでは、SQLとPL/SQLを使用してDBに対してクエリを実行します。私たちは、プロジェクトのデータベースエンジンにとらわれない小さな部分(最初は、すべてを最終的に変更する)を担当するように任されています。 Hibernate 3.3.2.GAと "* .hbm.xml"マッピングファイル(注釈とは対照的)を使用することを選択しました。残念ながら、従来のスキーマを後退させることはできないため、既存のスキーマを変更することは現実的ではありません。1対多のFKでも使用されている複合IDキープロパティに「insert = 'false' update = 'false'」をマップする方法はありますか?

私が遭遇している問題は、FKがでもの複合PKの一部である一方向性、1対多の関係をマップしようとしているときです。ここではクラスとマッピングファイル...

CompanyEntity.java

public class CompanyEntity { 
    private Integer id; 
    private Set<CompanyNameEntity> names; 
    ... 
} 

は、このコードは、単に作品CompanyNameEntity.java

public class CompanyNameEntity implements Serializable { 
    private Integer id; 
    private String languageId; 
    private String name; 
    ... 
} 

CompanyNameEntity.hbm.xml

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping package="com.example"> 

    <class name="com.example.CompanyEntity" table="COMPANY"> 
     <id name="id" column="COMPANY_ID"/> 
     <set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false"> 
      <key column="COMPANY_ID"/> 
      <one-to-many entity-name="vendorName"/> 
     </set> 
    </class> 

    <class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME"> 
     <composite-id> 
      <key-property name="id" column="COMPANY_ID"/> 
      <key-property name="languageId" column="LANGUAGE_ID"/> 
     </composite-id> 
     <property name="name" column="NAME" length="255"/> 
    </class> 

</hibernate-mapping> 

です名前の付いた会社のSELECTとINSERTには問題ありません。私は、既存のレコードを更新しようとしたときに問題が発生しました。私がされたBatchUpdateExceptionを受け、SQLのログを見た後、私は、Hibernateが

update COMPANY_NAME set COMPANY_ID=null where COMPANY_ID=? 

Hibernateはそれらを更新する前にDIS-准子レコードにしようとしていた...何か 愚かをやろうとした見ました。問題は、このフィールドがPKの一部であり、null不可能であることです。私は、Hibernateにこれを行わないようにする簡単な解決策が、親マッピングの "key"要素に "not-null = 'true'"を追加することであることを発見しました。だから今マッピングが...このように見えるかもしれ

CompanyNameEntity.hbm.xml

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
     "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
     "http://www.jboss.org/dtd/hibernate/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping package="com.example"> 

    <class name="com.example.CompanyEntity" table="COMPANY"> 
     <id name="id" column="COMPANY_ID"/> 
     <set name="names" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false"> 
      <key column="COMPANY_ID" not-null="true"/> 
      <one-to-many entity-name="vendorName"/> 
     </set> 
    </class> 

    <class entity-name="companyName" name="com.example.CompanyNameEntity" table="COMPANY_NAME"> 
     <composite-id> 
      <key-property name="id" column="COMPANY_ID"/> 
      <key-property name="languageId" column="LANGUAGE_ID"/> 
     </composite-id> 
     <property name="name" column="NAME" length="255"/> 
    </class> 

</hibernate-mapping> 

このマッピングは、例外を与える...今

org.hibernate.MappingException: Repeated column in mapping for entity: companyName column: COMPANY_ID (should be mapped with insert="false" update="false") 

私の問題は、私がしようと試みているということですこれらの属性をkey-property要素に追加しますが、これはDTDでサポートされていません。私はそれをキーの多対1の要素に変更しようとしましたが、それもうまくいきませんでした。したがって...

1対多数のFKでも使用されているコンポジットIDのキープロパティに「insert = 'false' update = 'false'」をマップする方法はありますか?

+0

を必要とマッピングすることができ、それが見えます。私はこれをもう少し試して、結果を掲載します。 –

+0

* .hbm.xmlファイルを使用して指定しようとしているマッピングは不可能です。これを達成する唯一の方法は、下記のmcyalcinの答えに記載されている注釈を使用することです。 –

+1

この投稿はXML設定の問題を解決するかもしれないと思います。http://stackoverflow.com/questions/9381029/hibernate-mapping-exception-repeated-column-in-mapping-for-entity –

答えて

77

私はあなたが探している注釈があると思う:

public class CompanyName implements Serializable { 
//... 
@JoinColumn(name = "COMPANY_ID", referencedColumnName = "COMPANY_ID", insertable = false, updatable = false) 
private Company company; 

そして、あなたは(23.4.2で)ここに示されているようのhbm.xmlに似たマッピングを使用することができるはずです。

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-mappings.html

+0

あなたの答えをありがとう。あなたが提供したJBossのドキュメントのリンク内に、私が問題を抱えているケースの例は含まれていません。私は彼らが示した方法とまったく同じようにマッピングを使ってみましたが、それはまだ私のためには機能しませんでした。私が達成しようとしている特定のマッピングは、現在のHBM DTD仕様では不可能であるようです。つまり、注釈付きのソリューションは、私が経験しているのと同じ問題に直面しないので、注釈を使用するオプションを持つ人にとっては良いソリューションです。私は通常、選択肢を持つ全員に注釈を推奨します。 –

+0

興味深い。今まではHibernateでアノテーションを使用していましたが、より便利だと思っていましたが、アノテーション機能はxmlマッピング定義のサブセットであったと思いました。本当に欠けている機能がある場合は、バグを報告する必要があるので、xmlを試してみます。私は答えが助けてうれしいです! – mcyalcin

+1

しかし、私が挿入して更新したい場合は、これを回避するための他の回避策がありますか? 私は、insertable = falseとupdatable = falseは "会社"を変更することはできません。 – kinshuk4

0

"Dino TW"は重要な情報を持つコメントHibernate Mapping Exception : Repeated column in mapping for entityへのリンクを提供しています。

セットのマッピングに "inverse = true"を提供するヒントがありました。試してみましたが、実際には動作します。SetキーとCompositeキーが一緒に来るというのはまれな状況です。 inverse = trueにすると、コンポジットキーが挿入されているテーブルのインサート&の更新はそのままになります。私はJPA/Hibernateのアノテーションを用いて所望のマッピングを作成することができるかもしれないように以下

はHibernateのアノテーションのドキュメントを見た後、

<class name="com.example.CompanyEntity" table="COMPANY"> 
    <id name="id" column="COMPANY_ID"/> 
    <set name="names" inverse="true" table="COMPANY_NAME" cascade="all-delete-orphan" fetch="join" batch-size="1" lazy="false"> 
     <key column="COMPANY_ID" not-null="true"/> 
     <one-to-many entity-name="vendorName"/> 
    </set> 
</class> 
関連する問題