我想用hibernate(在java中)實現一對多的關係。休眠:雙向一對多外鍵約束失敗
我有2個實體。
- 實驗
- ExperimentGroup
Experiment
有很多ExperimentGroups
。我試圖配置此一對多的關係,順便Hibernate官方文檔建議:http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/example-parentchild.html#example-parentchild-cascades
我的配置文件:
<class name="ExperimentImpl" table="Experiment">
<id name="id" type="int" column="id">
<generator class="increment" />
</id>
<!-- One to Many -->
<set name="experimentGroups" table="ExperimentGroup"
lazy="false" fetch="select" cascade="all" inverse="true">
<key>
<column name="Experiment_id" not-null="true" />
</key>
<one-to-many class="ExperimentGroupImpl" />
</set>
</class>
<class name="ExperimentGroupImpl" table="ExperimentGroup">
<id name="id" type="int" column="id">
<generator class="increment" />
</id>
<many-to-one name="experiment" class="ExperimentImpl" fetch="select">
<column name="Experiment_id" not-null="true" />
</many-to-one>
</class>
添加新ExperimentGroup
到Experiment
工作正常,但刪除實驗(和所有ExperimentGroups的)會導致異常:
不能刪除或更新父行:外鍵約束失敗 (
testdb
ExperimentGroup
,構造AINTFK9C71D86238B5500C
FOREIGN KEY(Experiment_id
)參考文獻Experiment
(id
))
我ExperimentDAO代碼如下所示:
public void deleteExperiment(Experiment experiment)
throws DAOException
{
Session session = null;
Transaction t = null;
try{
session = HibernateUtil.getSessionFactory().openSession();
t = session.beginTransaction();
session.delete(experiment);
t.commit();
session.flush();
session.close();
}catch (HibernateException e)
{
e.printStackTrace();
if (t != null)
t.rollback();
if (session != null)
session.close();
throw new DAOException(e, "Could not delete Experiment");
}
}
編輯: 的DAO代碼來創建一個實驗,ExperimentGroup
public Experiment createExperiment(String name, String description, RegisteredUser owner)
{
Transaction tx = null;
Session session = null;
try
{
session = HibernateUtil.getSessionFactory().openSession();
tx= session.beginTransaction();
ExperimentImpl e = new ExperimentImpl();
e.setName(name);
e.setDescription(description);
e.setOwner(owner);
owner.getOwnedExperiments().add(e);
session.save(e);
tx.commit();
session.flush();
session.close();
return e;
}catch (HibernateException ex)
{
if (tx != null)
tx.rollback();
if (session!=null)
session.close();
throw ex;
}
}
public ExperimentGroup createAndAddExperimentGroup(Experiment experiment, String experimentGroupName, Date startDate, Date endDate) throws ArgumentException
{
Transaction t = null;
Session session = null;
try
{
session = HibernateUtil.getSessionFactory().openSession();
t = session.beginTransaction();
ExperimentGroupImpl g = new ExperimentGroupImpl();
g.setEndDate(endDate);
g.setStartDate(startDate);
g.setName(experimentGroupName);
g.setExperiment(experiment);
experiment.getExperimentGroups().add(g);
g.setExperiment(experiment);
session.save(g);
session.update(experiment);
t.commit();
session.flush();
session.close();
return g;
}catch(HibernateException e)
{
if (t!=null)
t.rollback();
if (session!= null)
session.close();
throw e;
}
}
有一個對於實驗的其他屬性,比如我從配置文件中刪除的名稱,描述等,因爲它們對一對多關係沒有影響。
有什麼建議嗎?我錯了什麼?
錯誤提示休眠試圖刪除父Experimient實體而不先刪除所有ExperimentGroups。您可以發佈構建實驗/實驗組實體的代碼嗎? –
嗨,謝謝你的回答。我把代碼放在「問題」(上面)中。 – sockeqwe
@sockeqwe:你有外鍵約束的ON DELETE CASCADE子句嗎?如果不是,那麼情況很明顯:當你嘗試刪除父實體並且Hibernate遵循一對多關聯時,Hibernate首先刪除子實體,然後刪除父實體。如果Hibernate不知道這個關聯,那麼刪除父實體並不會導致刪除子項,這會導致違反約束。我不清楚,爲什麼你提供了'RegisteredUser'實體的代碼示例... –