【问题标题】:Hibernate: Many To Many Relation with attributes: correct configuration with AnnotationsHibernate:带有属性的多对多关系:带有注释的正确配置
【发布时间】:2011-12-20 13:12:09
【问题描述】:

我遇到了 Hibernate 问题(感谢 Thomas,现在问题更清晰了)。

简而言之:

当关系有属性并且需要级联保存、删除和更新时,如何配置与Hibernate的ManyToMany关联?

大尺寸:

想象以下数据库:

             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;

所以,我认为配置是正确的,并且如果用户有 Profile 子项,则可以独立保存所有这些。问题是当我尝试更新用户时:

 getHibernateTemplate().getSessionFactory().getCurrentSession().clear();
 getHibernateTemplate().saveOrUpdate( user );
 getHibernateTemplate().getSessionFactory().getCurrentSession().flush();

如果有一组空的 Profile 子项,Hibernate 不会删除 Profile 关系。只添加配置文件(覆盖旧的)......这很少见......有什么问题?

提前谢谢你

【问题讨论】:

    标签: java hibernate annotations cascade


    【解决方案1】:

    您实际上所做的只是删除关系,因此没有DELETE 可以级联,这就是为什么没有删除任何内容。

    尝试添加 Hibernate 级联类型 DELETE_ORPHAN(使用 @Cascade 注释)以使 Hibernate 删除不再引用的实体。

    此外,我不会单独删除 Mini 实体。如果没有关系,即 Minis 的集合是空的,那么保留现在代表空集合的 SuperMini 实体通常是没有意义的(在极少数情况下它可能是有意义的,只是想让你考虑一下是否不管你是否需要它们)。

    编辑

    请注意,DELETE_ORPHAN 应该重用该集合,否则可能会删除并重新插入所有关系。

    基本上,Hibernate 会看到该集合被更改,并会删除“旧”集合并重新插入“新”集合。这可能是需要的,但如果您只想要更新,即只删除不在集合中的实体,您应该执行以下操作:

    1. 清除设置
    2. 使用addAll(...) 将“新”集添加到已重用且现已清除的集

    这应该只触发更新(和删除孤儿)。

    【讨论】:

    • 首先:感谢您的回答。如果对象 Super 有一组 Mini 并且我用空集更新 Super 实体中的集合,我需要 Hibernate 从 SuperMini 实体启动删除。
    • 请注意,实际上这是一个 M-N 关系,而不是 1M 关系。我只需要删除超级实体和迷你实体之间的关系,而不是迷你实体。
    • @ganzux 正如我所说,您需要Super 中的superMini 关系上的DELETE_ORPHAN 级联类型。但是要记住一件事:您应该重复使用该集合。我会相应地更新我的答案。
    • 所以 SuperMini 类,在 Super 关系中,我将 @Cascade({CascadeType.LOCK}) 更改为 @Cascade({CascadeType.DELETE_ORPHAN}) 。是吗?
    • @ganzux 我刚刚再次查看了您的代码:您没有将SuperMini 中的级联类型添加到Super 中的superMini 属性中。我在那里看不到任何CascadeType.LOCK,所以我假设你把它放在了错误的关系上。您还可以更新您的问题以反映您所做的更改。 - 顺便说一句,你实际上没有private Super super;,是吗?这甚至不应该编译(super 是保留关键字)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 2013-08-29
    • 1970-01-01
    • 2020-03-04
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多