2

休止状態での mysql スキーマの生成に問題があります。私は自分の問題に対する答えを探しましたが、見つかりませんでした (多くの同様の問題がありますが、正確には私のものではありません)。

ステート ダイアグラムを mysql (または遷移テーブル) にマップし、カスケードでステートを削除する必要があります。State は、複数の State を子として持つことができます (多対多の関係)。State クラスと「次の状態」の関係のマッピングには成功しましたが、正しい SQL オプション ON DELETE CASCADE の生成には成功しませんでした。

Java クラスは次のとおりです。

public class State {
private Integer version;
private Integer oid;
private String name;
private Map<String, State> nextStates;

public State(String name) {
    super();
    this.name = name;
    this.nextStates = new HashMap<String, State>();
}

/**
 * Adds some state to the transitions table. 
 * The table is indexed by states names.
 * 
 */
public void addNextState(State s) {
    this.nextStates.put(s.getName(), s);
}
(...)

休止状態の構成は次のとおりです。

<hibernate-configuration>
<session-factory>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost/testStatesDB</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">pass</property>
    <property name="hibernate.connection.pool_size">10</property>
    <property name="show_sql">true</property>
    <property name="format_sql">true</property>     
    <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
    <property name="hibernate.hbm2ddl.auto">create-drop</property>
    <property name="hibernate.bytecode.use_reflection_optimizer">false</property>       
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <mapping resource="State.hbm.xml" />
</session-factory>
</hibernate-configuration>

状態のマッピングは次のとおりです。

<hibernate-mapping>
<class name="State" table="state" optimistic-lock="version">
    <id name="oid" column="OID">
        <generator class="increment" />
    </id>
    <version column="version" name="version" unsaved-value="null"/>     

    <property name="name" type="java.lang.String"/>

    <map name="nextStates" table="nextStates" cascade="delete" optimistic-lock="true"> 
            <key column="parentState_oid" /> 
            <index column="children_stateName" type="java.lang.String"/> 
            <many-to-many column="children_oid" class="State" /> 
    </map>
</class>
</hibernate-mapping>

次のスキーマを作成します。

Hibernate: 
create table nextStates (
    parentState_oid integer not null,
    children_oid integer not null,
    children_stateName varchar(255) not null,
    primary key (parentState_oid, children_stateName)
) ENGINE=InnoDB

Hibernate: 
create table state (
    OID integer not null,
    version integer not null,
    name varchar(255),
    primary key (OID)
) ENGINE=InnoDB

Hibernate: 
alter table nextStates 
    add index FKB4A102D5587BDC23 (parentState_oid), 
    add constraint FKB4A102D5587BDC23 
    foreign key (parentState_oid) 
    references state (OID)

Hibernate: 
alter table nextStates 
    add index FKB4A102D5F71F7FB (children_oid), 
    add constraint FKB4A102D5F71F7FB 
    foreign key (children_oid) 
    references state (OID)

例として、次のテスト コードを実行することを検討してください。

State pend   = new State("Pending");
State dev   = new State("In development");
State finali = new State("Finalized");

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

pend.addNextState(dev);
dev.addNextState(finali);
dev.addNextState(pend);

session.save(pend);
session.save(dev);
session.save(finali);
session.getTransaction().commit();

session.beginTransaction();
dev = (State)session.load(State.class, 3);
session.delete(dev);
session.getTransaction().commit();

次のエラー メッセージが表示されます。

Cannot delete or update a parent row: a foreign key constraint fails (`testStatesDB`.`nextstates`, CONSTRAINT `FKB4A102D5F71F7FB` FOREIGN KEY (`children_oid`) REFERENCES `state` (`OID`))

データベースにアクセスして、生成された外部キーにプロパティ ON DELETE CASCADE を追加すると、この例は必要に応じて機能します。

問題は、これは HashMaps を使用して多対多の関係をマッピングする正しい方法ですか? それが正しければ、Hibernate xml マッピングを使用して ON DELETE CASCADE オプションを生成するにはどうすればよいですか?

私は長い間この問題に取り組んできましたが、良い解決策が見つかりませんでした。

4

2 に答える 2

1

私は問題を部分的に解決しました: クラス State と State の間に双方向の関係を使用しました (はい、再帰関係が機能しました)。各状態には、グラフ内の次の状態のマップと、親状態のマップがあります。

delete="cascade" オプションは、私が望むように ON DELETE CASCADE を生成しませんでしたが、状態内のコレクションを同期させておく限り、カスケードで削除できます。「同期」とは、状態 S1 が次の状態として S2 を持っている場合、S1 の次の状態 S2 を削除する場合、S1 が親ではなくなったことを S2 に知らせる必要があることを意味します。

これが誰かの助けになることを願っています...私はこの問題で長い間立ち往生していました。

ありがとうございました。イグナシオ

于 2012-10-18T00:14:18.087 に答える
0

キーに on delete カスケードを設定できます

<key column="parentState_oid" on-delete="cascade" />
于 2012-09-14T10:08:47.920 に答える