hibernate @ManyToMany中的两个外键

kb5ga3dv  于 2023-02-13  发布在  其他
关注(0)|答案(2)|浏览(144)

我正在做一个宠物项目,我需要实现朋友功能。所以,例如我有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;

但是再一次,我得到了和以前一样的错误。
C × aused 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)

但是我试过了日志中所有的技巧,都不起作用。
那么,总的来说,我怎样才能从同一个实体中创建一个有两个外键的表,并能在以后持久化数据呢?

lndjwyie

lndjwyie1#

我假设朋友请求不仅是用户之间的连接,而且还携带着是否接受这样的数据,因此我将使用第二种方法,将朋友请求表示为它自己的实体(在这种情况下,我将把UserUser重命名为FriendRequest)。这样,发送方和接收方的名称就不同了,例如,类似这样的东西(我现在无法测试,所以它只是我的头顶-谨慎使用):

@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

ma8fv8wu

ma8fv8wu2#

@JoinTable注解对两个连接方向使用相同的列。

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

反向联接应为:inverseJoinColumns = @JoinColumn(name = "receiver_id")

相关问题