【问题标题】:Two Foreign keys in @ManyToMany@ManyToMany 中的两个外键
【发布时间】:2023-02-07 20:47:21
【问题描述】:

我在做一个宠物项目,我需要实现朋友功能。因此,例如我有 user 实体。
我需要与两个外键建立@ManyToMany关系。 SQl显式创建表的例子:

create table friend_request(
    id int primary key
    ,sender_id int
    ,receiver_id int

    ,foreign key (sender_id) references users (user_id)
    ,foreign key (receiver_id) references users (user_id)
);

它已成功创建,但我不知道如何将此表“连接”到实际业务逻辑。

我试过这样创建。

@Entity(name = "friend_request")
@Data
@NoArgsConstructor
public class UserUser {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;


    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_user",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "user_id")
    )
    private List<User> users;
    


}

这是 User 类中的代码:

@ManyToMany(mappedBy = "users")
private List<UserUser> user;

但是我得到了这个错误:

Caused by: org.hibernate.MappingException: Repeated column in mapping for collection: ua.socialnetwork.entity.User.user column: user_id
    at org.hibernate.mapping.Collection.checkColumnDuplication(Collection.java:409) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.mapping.Collection.checkColumnDuplication(Collection.java:433) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.mapping.Collection.validate(Collection.java:391) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:380) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:301) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) ~[spring-orm-6.0.3.jar:6.0.3]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[spring-orm-6.0.3.jar:6.0.3]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.0.3.jar:6.0.3]
    ... 25 common frames omitted

另外,我找到了一种创建多个 @OneToOne 的方法,所以我尝试了这个:

这是UserUser类:

@Entity(name = "friend_request")
@Data
@NoArgsConstructor
public class UserUser {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;


    @ManyToOne
    @JoinColumn(name = "user_id")
    private User sender;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User receiver;
}

User 类中的代码:

@OneToMany(mappedBy = "sender")
private List<UserUser> senders;

@OneToMany(mappedBy = "receiver")
private List<UserUser> receivers;

但是,我又遇到了和以前一样的错误。
Caused by: org.hibernate.MappingException: Column 'user_id' is duplicated in mapping for entity 'ua.socialnetwork.entity.UserUser' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)

它说要使用

@Column(insertable=false, updatable=false)

但我从日志中尝试了所有这些和下一个技巧,但都没有用。

所以,总的来说,我如何创建一个表,其中包含来自同一实体的 2 个外键,并且能够在以后保留数据?

【问题讨论】:

    标签: java sql database hibernate many-to-many


    【解决方案1】:

    我假设好友请求不仅是用户之间的连接,而且还携带数据,比如它是否被接受,所以我会使用第二种方法将好友请求表示为它自己的实体(我会重命名UserUserFriendRequest 在这种情况下)。然后发送者和接收者将被命名为不同的,例如像这样的东西(我现在无法测试它所以它只是在我的脑海中 - 谨慎使用):

    @Entity(name = "friend_request")
    @Data
    @NoArgsConstructor
    public class FriendRequest {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        //add additional data as needed
    
        @ManyToOne
        @JoinColumn(name = "sender_id")
        private User sender;
    
        @ManyToOne
        @JoinColumn(name = "receiver_id")
        private User receiver;
    }
    
    @Entity(name = "user") 
    //other annotations
    public class User {
       @OneToMany(mappedBy = "sender")
       private List<FriendRequest> sentRequest;
    
       @OneToMany(mappedBy = "receiver")
       private List<FriendRequest> receivedRequests;
    }
    

    您几乎是正确的,但是您的方法有一个错误:连接列名称是包含外键的列的名称,而不是引用的列名称,即 sender_idreceiver_id 但不是 user_id

    【讨论】:

      猜你喜欢
      • 2017-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多