Hibernate:与属性的多对多关系:使用注释进行正确配置
我在使用 Hibernate 时遇到了问题(感谢 Thomas,现在问题更加清晰了)。
简而言之:
当关系具有属性并且我们需要级联保存、删除和更新时,如何配置与 Hibernate 的多对多关联?
大图:
想象一下以下数据库:
User Profile
M______N
|
attribute
这里有 3 个表:
"User", "Profile" and "User_Profile".
现在假设 User_Profile 有 1 个关系属性(显然还有键)。
好的,现在这将通过以下方式转换为 Hibernate:
User:
// The relation is Many to Many, but considering that it has an attribute, this is OneToMany with the ManyMany RelationShip
@OneToMany(mappedBy="user", targetEntity=UserProfile.class)
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
@LazyCollection(LazyCollectionOption.TRUE)
private Set<UserProfile> userProfile = new HashSet<UserProfile>();
UserProfile:
@Id
@ManyToOne(targetEntity=User.class,fetch=FetchType.LAZY)
@Cascade({CascadeType.LOCK})
@JoinColumns({ @JoinColumn(name="...", referencedColumnName="...") })
private User user;
@Id
@ManyToOne(targetEntity=Profile.class,fetch=FetchType.LAZY)
@Cascade({CascadeType.LOCK})
@JoinColumns({ @JoinColumn(name="...", referencedColumnName="...") })
private Profile profile;
因此,我认为配置是正确的,并且如果用户有配置文件子级保存所有配置文件,则独立保存。问题是当我尝试更新用户时:
getHibernateTemplate().getSessionFactory().getCurrentSession().clear();
getHibernateTemplate().saveOrUpdate( user );
getHibernateTemplate().getSessionFactory().getCurrentSession().flush();
如果存在一组空的配置文件子项,Hibernate 不会删除配置文件关系。仅添加配置文件(覆盖旧的)...这很少见...有什么问题?
先感谢您
I have a problem with Hibernate (Thanks to Thomas now the problem is more legible).
In Short:
How to configure a ManyToMany association with Hibernate when the relationship has an attribute and we need save, delete and update in cascade?
In Large:
Imagine the following DataBase:
User Profile
M______N
|
attribute
There are 3 tables here:
"User", "Profile" and "User_Profile".
Now imagine User_Profile has 1 attribute for the relation (and obviously the keys).
Ok, now this is translating to Hibernate by the following:
User:
// The relation is Many to Many, but considering that it has an attribute, this is OneToMany with the ManyMany RelationShip
@OneToMany(mappedBy="user", targetEntity=UserProfile.class)
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
@LazyCollection(LazyCollectionOption.TRUE)
private Set<UserProfile> userProfile = new HashSet<UserProfile>();
UserProfile:
@Id
@ManyToOne(targetEntity=User.class,fetch=FetchType.LAZY)
@Cascade({CascadeType.LOCK})
@JoinColumns({ @JoinColumn(name="...", referencedColumnName="...") })
private User user;
@Id
@ManyToOne(targetEntity=Profile.class,fetch=FetchType.LAZY)
@Cascade({CascadeType.LOCK})
@JoinColumns({ @JoinColumn(name="...", referencedColumnName="...") })
private Profile profile;
So, I think the configuration is correct, and the save, independently if the User has Profile childrens save all of them. The problem is when I try to update the user:
getHibernateTemplate().getSessionFactory().getCurrentSession().clear();
getHibernateTemplate().saveOrUpdate( user );
getHibernateTemplate().getSessionFactory().getCurrentSession().flush();
Hibernate don´t delete the Profile relation if there is an empty set of Profile childrens. Only add the profiles (override the old)... That´s rare... What´s the problem?
Thank you in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您实际上所做的就是删除关系,因此没有
DELETE
进行级联,这就是为什么没有删除任何内容。尝试添加 Hibernate 级联类型
DELETE_ORPHAN
(使用@Cascade
注释)以使 Hibernate 删除不再引用的实体。此外,我不会单独删除
Mini
实体。如果没有关系,即Mini
集合为空,则保留现在代表空集合的SuperMini
实体通常没有任何意义(在极少数情况下可能会有道理,只是想让你考虑是否需要它们)。编辑:
请注意,使用
DELETE_ORPHAN
时,您应该重用该集,否则所有关系可能会被删除并重新插入。基本上,Hibernate 会看到该集被更改,并会删除“旧”集并重新插入“新”集。这可能是需要的,但如果您只想更新,即只删除不再存在于集合中的实体,您应该执行以下操作:
这应该仅触发更新(和删除孤儿)。
All you actually do is remove the relation and thus theres no
DELETE
to cascade, that's why nothing gets deleted.Try adding the Hibernate cascade type
DELETE_ORPHAN
(using the@Cascade
annotation) to make Hibernate delete entities that are not referenced anymore.Additionally, I'd not remove the
Mini
entities alone. If there's no relation, i.e. the set ofMini
s is empty, it normally makes no sense to keep theSuperMini
entities that now represent an empty collection (in rare cases it might make sense, just want you to think about whether you need them or not).Edit:
Note that with
DELETE_ORPHAN
you should reuse the set, otherwise all the relations might be deleted and reinserted.Basically Hibernate would then see the set being changed and would issue a delete for the "old" set and a reinsert for the "new" set. This could be wanted but in case you only want an update, i.e. only delete the entities that are not in the set anymore, you should do the following:
addAll(...)
This should trigger the update (and deletion of orphans) only.