2009-05-11 22 views
1

私は、2つのレガシーデータベーステーブルを持って、このような簡略化された方法でレイアウトさき:(休止状態)

MASTER      SLAVE 
ident       ident 
sName       sName 
sNumber      sNumber 
sDesc       sValue 
-----       ------ 
Java Class 'ScenarioMaster' Java Class 'ScenarioSlave' 

各行は、サロゲートを持っていますインデックスはident列を使用しますが、MASTER.keySLAVE.keyの間には関係がありません。ただし、MASTERテーブルの場合、1つのsName/sNumberペアの一意性はtrueです。したがって、これは可能かつ意味のある複合キー(私はそれらが悪であることを知っています)です。

は、実際には、1がある:Nの関係はSLAVEテーブルの各MASTER行参照N行を意味します。上記の列の記述を考えると、可能な人口は、私は私のJavaクラスでは、この関係を反映することができるか、休止状態を使用して今

MASTER      SLAVE 
100       42 
'labl'      'labl' 
1        1 
'some label'     0.1 
           43 
          'labl' 
           1 
           0.2 

、だろうか?すでにを更新するときScenarioMasterでは、私は

<bag name="slaves" cascade="all"> 
    <key> 
     <column name="sName" not-null="true"/> 
     <column name="sNumber" not-null="true"/> 
    </key> 
    <one-to-many class="ScenarioSlave"/> 
</bag> 

これを含めることができScenarioMasterため

private List<ScenarioSlave> slaves = new ArrayList<ScenarioSlave>(); 

などの公共ゲッター/セッターのhibernate-マッピングで設定またはリストを宣言し、しかし、strage UPDATE文を作成し、エンティティScenarioMasterエンティティsession.saveOrUpdate(scenarioMaster)を使用しています。

// create master scn and slave slv  
scn.addSlave(slv); 
session.saveOrUpdate(scn); 

    Hibernate: 
     update 
      SLAVE 
     set 
      sNumber=?, 
      sName=?, 
      sValue=? 
     where 
      sName=? 
      and sNumber=? 
    Hibernate: 
     update 
      SLAVE 
     set 
      sName=null, 
      sNumber=null 
     where 
      sName=? 
      and sNumber=? 

私は間違っていますか?その2回目のアップデートはどこから来たのですか? 私はsName/sNumberと何か関係があると思います。ScenarioSlaveのキーではありません。私は、なぜ、理解できないのですか。 SNAME/sNumberパラメータが有効な値にポイントを行うと、私はsaveOrUpdateを通じて持続したいScenarioMasterインスタンスが実際にslavesリストにnull以外のScenarioSlaveインスタンスを持っていることを

は注意してください。

EDIT:複合キーがこのマッピング私は本当にテーブルのようなものに「labl」をマッピングしNAMENUMBER_KEY、1を作成したくない

<composite-id name="keyId" class="ScenarioKeyId"> 
    <key-property name="name" access="field" column="sName" 
     type="string" length="20"/> 
    <key-property name="number" access="field" column="sNumber" 
     type="long"/> 
</composite-id> 

を使用して別のクラスに延期されます'key_labl1'これは、次に、休止状態にidとして使用することができます。これは、(実際のテーブルを使わずに)休止状態がするものです。

答えて

2

私の経験上、Hibernateは複合キーではうまく動作しません。私が見た限り、これはHibernateの主な問題の1つです。私は過去に「純粋に」コンポジットキーの使用を避けることでそれを回避しました。すなわち、コンポジット・キー・テーブルに、ユニバーサルIDカラムを与えました。これにより、Hibernateは動作します。

+1

私たちのうちの2人(ユニークなIDカラムの導入について) – Schildmeijer

+0

私はそのソリューションを使用/使用する唯一の人ではないことを知っておいてください。 DB設計の観点からすると、少しイライラしますが、実際に問題を改善します。 –

+0

あなたはそのアプローチについて詳しく説明できますか? '複合キーテーブルに一意のID列'が指定されていると、テーブルを変更しますか?私はこれをすることができないのではないかと心配していますが、これもあなたがしたことではないのです。 – msi

0

私はちょっと試してみた(Apache Derby)、両方のテーブルにコンポジットIDがありません。 次に、SET ... = nullの文がslaveリストのメンバーを無効にするために発行されている可能性が高いことが分かりました。

create table MASTER(
    ident numeric(10) not null, -- key column 
    name char(20) not null, 
    number numeric(10) not null, 
    descr char(64) not null 
); 

create table SLAVE(
    ident numeric(10) not null, -- key column 
    name char(20) not null, 
    number numeric(10) ,  -- foreign key f. MASTER.ident 
    value float not null 
); 

ここは私のテストコードです。マスタークラスキーのジェネレータをassignedに設定しました。

その後
 Master master = new Master(); 
     master.setIdent(Integer.valueOf(0)); 
     master.setName("name"); 
     master.setNumber(42); 
     master.setDescr("name/42 descr"); 
     Slave slv = new Slave("name", 42, 0.001); 
     master.addSlave(slv); 
     theSession.beginTransaction(); 
     theSession.saveOrUpdate(master); 
     theSession.getTransaction().commit(); 

は、SLAVE.number行のNULL値をできるように、私は今、私が唯一の実際NULLに外部キー列を設定するというし、SLAVEに古い行を削除する方法を把握する必要があり

Hibernate: 
    update 
     SLAVE 
    set 
     number=null 
    where 
     number=? 
Hibernate: 
    update 
     SLAVE 
    set 
     number=? 
    where 
     ident=? 

を取得します...