hibernate不会在mysql中为删除级联生成HashMap的映射

时间:2012-09-06 23:50:01

标签: mysql hibernate hashmap cascade cascading-deletes

我在使用hibernate生成mysql架构时遇到问题。我已经搜索了我的问题的答案,但我没有找到它(许多类似的问题,但不完全是我的)。

我需要将状态图映射到mysql(或转换表),并以级联方式删除状态。一个国家可能有许多国家作为儿童(多对多关系)。我成功映射了State类和“next 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配置是:

<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选项?

我一直在处理这个问题很长一段时间,但我没有找到一个好的解决方案。

2 个答案:

答案 0 :(得分:1)

我已经部分地解决了这个问题:我在类State和State之间使用了双向关系(是的,递归关系工作)。在每个州,我都有一张地图用于图中的下一个状态,另一个用于父状态。

delete =“cascade”选项没有像我希望的那样生成ON DELETE CASCADE,但是,只要我将集合保持在状态同步中,我就可以级联删除。通过“同步”,我的意思是如果状态S1将S2作为下一状态,那么如果你在S1中删除下一个状态S2,你还必须让S2知道S1不再是它的父级。

我希望这能有所帮助......我长期以来一直困扰着这个问题。

谢谢。 伊格纳西奥

答案 1 :(得分:0)

您可以在键上设置删除级联

<key column="parentState_oid" on-delete="cascade" />