【问题标题】:Many-to-many on the same table with additional columns同一张表上的多对多,带有额外的列
【发布时间】:2009-12-02 07:21:39
【问题描述】:

我有一个类用户。一个用户可以与许多其他用户成为朋友。关系是相互的。如果 A 是 B 的朋友,那么 B 是 A 的朋友。另外,我希望每个关系都存储额外的数据——例如两个用户成为朋友的日期。所以这是同一个表上的多对多关系,带有额外的列。我知道应该创建一个中产阶级友谊(包含两个用户 ID 和日期列)。但是我在用 Hibernate 映射这个方面做得很短。阻止我的是映射到同一张表。如果多对多关系在两个不同的表之间,我可以解决它。

【问题讨论】:

    标签: hibernate mapping many-to-many orm


    【解决方案1】:

    你说过

    多对多关系在同一张桌子上

    这不是一个好主意。维护是一场噩梦。

    试试这个

    @Entity
    public class Friend {
    
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private Integer friendId;
    
        @Column
        private String name;
    
        @OneToMany(mappedBy="me")
        private List<MyFriends> myFriends;
    
    }
    
    @Entity
    public class MyFriends {
    
        @EmbeddedId
        private MyFriendsId id;
    
        @Column
        private String additionalColumn;
    
        @ManyToOne
        @JoinColumn(name="ME_ID", insertable=false, updateable=false)
        private Friend me;
    
        @ManyToOne
        @JoinColumn(name="MY_FRIEND_ID", insertable=false, updateable=false)
        private Friend myFriend;
    
        @Embeddable
        public static class MyFriendsId implements Serializable {
    
            @Column(name="ME_ID", nullable=false, updateable=false)
            private Integer meId;
    
            @Column(name="MY_FRIEND_ID", nullable=false, updateable=false)
            private Integer myFriendId;
    
            public boolean equals(Object o) {
                if(o == null)
                    return false;
    
                if(!(o instanceof MyFriendsId))
                    return false;
    
                MyFriendsId other = (MyFriendsId) o;
                if(!(other.getMeId().equals(getMeId()))
                    return false;
    
                if(!(other.getMyFriendId().equals(getMyFriendId()))
                    return false;
    
                return true;
            }
    
            public int hashcode() {
                // hashcode impl
            }
    
        }
    
    
    }
    

    问候,

    【讨论】:

    • 感谢您的回答。但我有一个问题。为什么将“insertable = false”放在@ManyToOne 关系中?如果我删除它,那么它可以工作。否则 MyFriends 无法正确持久化。我不是 Hibernate 专家,所以可能我不明白。
    • 好的,我没有使用像你这样的 EmbeddedId,而只是另一个 id 列。您已经放置了 insertable=false ,因为 EmbeddedId 会处理它。你的回答被接受:)
    • 你已经注意到原因了。当两个属性共享同一列时,最好将有关它的设置放在一个属性中。否则,Hibernate 会报错。
    • 您好,我已阅读您的帖子。我有一个问题,在哪里可以找到映射这些实体类的 SQL 脚本?
    • 我想知道,为什么 Embeddable 类是静态的?据我所知,静态类保留在内存中,并且在整个应用程序关闭之前不会被垃圾收集。如我错了请纠正我。谢谢!
    【解决方案2】:

    我不确定这是否适合您的情况,但请尝试一下。

    @Entity
    public class Friend {
    
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private int friendId;
    
        @Column
        private String name;
    
        @ManyToMany(mappedBy="owner")
        private List<Friendship> friendships;
    }
    
    @Entity
    public class Friendship {
    
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private int friendshipId;
    
        @OneToOne
        private Friend owner;
    
        @OneToOne
        private Friend target;
    
       // other info
    }
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题。你可以试试这样:

      <class name="Friend" entity-name="RelatedFriend" table="FRIENDS">
          <id name="id" type="long">
              <generator class="native" />
          </id>
      
          <!-- *** -->
      
          <set name="relatedFriends" table="RELATED_FRIENDS">
              <key column="FRIEND_ID" />
              <many-to-many column="RELATED_FRIEND_ID" class="Friend" entity-name="RelatedFriend"/>
          </set>
      </class>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-13
        • 2018-02-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多