我已經查找了如何在休眠中實現以下關聯的信息,雖然hibernate手冊非常詳盡,但我還沒有找到解決以下用例。如何在java中用hibernate正確實現owner-owned-owner2關聯?
我有一個要求與實體之間的關聯,其中關聯除了關聯實體的外鍵之外還有幾個屬性。關係的規格如下:
- 容器與通過位置包含關聯。
- 沒有Container和Contained項目的情況下,職位不能存在。
- 因此,如果Container或Contained項目被刪除,則應刪除Position。
- 容器可以包含0個或更多位置。
- 一個位置是指一個且只有一個包含的項目。
我已經成功地通過註釋配置了大部分需求,除了級聯從Contained項目中刪除外,它工作得非常好。我有一個工作要做到這一點下面描述,但我想通過註釋配置此操作,讓數據庫自動執行工作,以便具有更強大的參照完整性。
這是映射的是我到目前爲止有:
@Entity
public class Container
{
@OneToMany(cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.EAGER)
@JoinColumn(name = "container_fk")
public Set<Position> getPositions() { return this.positions; }
public void setPositions(final Set<Position> positions) { this.positions = positions; }
private Set<Position> positions;
...
}
@Entity
public class Position
{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "container_fk", insertable = false, updatable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
public Container getContainer() { return this.container; }
public void setContainer(Container container) { this.container = container; }
private Container container;
@NaturalId
@OneToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "contained_fk")
public Contained getContained() { return this.contained; }
public void setContained(Contained contained) { this.contained = contained; }
private Contained contained;
// other attributes are owned by this relationship
// (i.e., they don't make sense in either Container or Contained.
...
}
要刪除的位置,刪除包含的項目下面是在代碼實現的ContainedDao時(呈現無異常處理和會話管理完成在基DAO類爲簡單起見):
@Repository
@Transactional(rollbackFor = Throwable.class)
public class ContainedDao extends TransactionalDao<Contained>
{
public void delete(String id)
{
final Session session = getSession();
// If there is a Position associated to the Contained item delete it,
// and remove it from any Container collection.
Position position = (Position) session.createCriteria(Position.class)
.createCriteria("contained")
.add(Restrictions.eq("id", id))
.uniqueResult();
if (position != null)
{
position.getContainer().getPositions().remove(position);
session.delete(position);
}
// Delete the Contained item.
Contained object = session.load(Contained.class, id);
session.delete(contained);
}
}
我想要做的就是以某種方式通過註釋配置,以便讓ContainedDao.delete方法被簡化爲一個簡單的:
// Delete the Contained item.
Contained object = session.load(Contained.class, id);
session.delete(contained);
這可能嗎?或者,我現在的解決方案是最好的?有沒有更好的方法來解決這個問題?請注意,這裏的關鍵因素是Position包含附加屬性;否則,我將直接配置Container/Contained之間的關聯並讓hibernate管理關聯。
有沒有什麼辦法可以澄清這個問題,以便評估我是否找到了我所希望的最佳解決方案,或者是否有辦法讓數據庫爲提高參照完整性做好工作? – miguelf
你寫過一個職位只有一個Contained。在其生命週期中,Position實例是否有可能指向兩個或更多個不同的Contained項目? (即你是否打算將外鍵更新爲Contained in Position) –
不,我把它作爲一個不可變屬性。因此,如果您希望指向另一個包含的位置,您將刪除該位置並創建一個新位置。具有position元素的主要原因是由於語義以及因爲它允許在延遲加載包含的對象時獲取這些屬性而保持與關聯相關的屬性。 – miguelf