我已经查找了如何在休眠中实现以下关联的信息,虽然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