我正在做一个宠物项目,我需要实现朋友功能。所以,例如我有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)
但是我试过了日志中所有的技巧,都不起作用。
那么,总的来说,我怎样才能从同一个实体中创建一个有两个外键的表,并能在以后持久化数据呢?
2条答案
按热度按时间lndjwyie1#
我假设朋友请求不仅是用户之间的连接,而且还携带着是否接受这样的数据,因此我将使用第二种方法,将朋友请求表示为它自己的实体(在这种情况下,我将把
UserUser
重命名为FriendRequest
)。这样,发送方和接收方的名称就不同了,例如,类似这样的东西(我现在无法测试,所以它只是我的头顶-谨慎使用):你几乎做对了但你的方法有一个错误:连接列名是包含外键的列的名称,而不是引用的外键,即
sender_id
和receiver_id
,但不是user_id
。ma8fv8wu2#
@JoinTable
注解对两个连接方向使用相同的列。反向联接应为:
inverseJoinColumns = @JoinColumn(name = "receiver_id")