Java JPA中的自参考场映射
假设我们有用户实体类。用户可以与其他用户成为朋友。在不创建名为Connection的新实体或在数据库中创建多个条目的情况下,如何映射此自引用集合字段Java JPA中的自参考场映射,java,jpa,eclipselink,Java,Jpa,Eclipselink,假设我们有用户实体类。用户可以与其他用户成为朋友。在不创建名为Connection的新实体或在数据库中创建多个条目的情况下,如何映射此自引用集合字段 @Entity public class User { ... @ManyToMany private Collection<User> friends; ... } USER_ID-FRIEND_ID 1 - 2 2 - 1 (duplicate... I don't need it) @实体 公共类用户{ ... @许多 私人收
@Entity
public class User {
...
@ManyToMany
private Collection<User> friends;
...
}
USER_ID-FRIEND_ID
1 - 2
2 - 1 (duplicate... I don't need it)
@实体
公共类用户{
...
@许多
私人收藏朋友;
...
}
用户\u ID-朋友\u ID
1 - 2
2-1(重复…我不需要它)
您不能-您需要数据库中的两条记录
实际上,对于友谊关系,我认为像neo4j这样的图形数据库是合适的。这里有两个用户,只需添加一个边缘“friends”(好友)。以下是我的ElementEntity代码中的快照:
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private List<ElementEntity> children;
@JoinColumn(name = "ParentId", referencedColumnName = "ElementId")
@ManyToOne(fetch = FetchType.LAZY)
private ElementEntity parent;
@OneToMany(mappedBy=“parent”,fetch=FetchType.LAZY)
私人名单儿童;
@JoinColumn(name=“ParentId”,referencedColumnName=“ElementId”)
@manytone(fetch=FetchType.LAZY)
私有元素实体母公司;
在数据库中,有以下字段:
-主键李>ElementId
与父项的关系ParentId
关系表
因此,您有一个用户
表和一个朋友
:
user_id friend_id
1 2
但是@Bozho的答案比我的要好得多(neo4j
) 嗯,事实上你可以
您可以使用@PreUpdate、@PrePersists、@postpdate等注释手动转换集合的元素。这样,您的实体就可以按您想要的方式呈现它们,而在数据库中只存储原始文本
一个更容易暂停的替代方法是使用@Convert注释,该注释自JPA2.1(hibernate中的@UserType)开始提供。它告诉jpa每次在数据库中读取/保存字段时将其转换为另一种类型。
对于它,您应该使用@Convert anotion,指定和AttributeConverter对象
比如说
public class Parent {
@Id
private Integer id;
@Convert(converter = FriendConverter.class)
private Set<Parent>friends;
}
公共类父类{
@身份证
私有整数id;
@Convert(converter=FriendConverter.class)
私人朋友;
}
和转换器类,如下所示:
@Component
public class FriendConverter implements AttributeConverter<List, String>{
@Autowired
private SomeRepository someRepository;
@Override
public String convertToDatabaseColumn(List attribute) {
StringBuilder sb = new StringBuilder();
for (Object object : attribute) {
Parent parent = (parent) object;
sb.append(parent.getId()).append(".");
}
return sb.toString();
}
@Override
public List convertToEntityAttribute(String dbData) {
String[] split = dbData.split(".");
List<Parent>friends = new ArrayList<>();
for (String string : split) {
Parent parent = someRepository.findById(Integer.valueOf(string));
friends.add(accion);
}
return friends;
}
}
@组件
公共类FriendConverter实现AttributeConverter{
@自动连线
私有存储库;
@凌驾
公共字符串convertToDatabaseColumn(列表属性){
StringBuilder sb=新的StringBuilder();
for(对象:属性){
父对象=(父对象);
sb.append(parent.getId()).append(“.”);
}
使某人返回字符串();
}
@凌驾
公共列表convertToEntityAttribute(字符串dbData){
字符串[]split=dbData.split(“.”);
Listfriends=newarraylist();
用于(字符串:拆分){
Parent Parent=someRepository.findById(Integer.valueOf(string));
添加(accion);
}
回报朋友;
}
}
这是一个虚拟实现,但它提供了一个想法
作为个人评论,我确实建议按照应该的方式绘制关系图。在未来,它将避免你的问题。AttributeConverter在使用枚举时非常方便。。。我想可能是作弊或作弊。这个答案不正确。自引用多对多关系是有效的,可以在JPA中映射,而无需定义任何新实体。这段关系需要一个桥牌,就像所有多对多的关系一样。谢谢你抽出时间。我不是在寻找父子关系。@HayatiGuvence出了什么问题-只需将ParentId重命名为USER_ID,将elementId重命名为friend_ID:)表中不能有两个相同的列名自引用多对多关系是有效的,可以使用JPA注释进行映射。与所有多对多关系一样,必须定义一个桥接表来存储关系的双方。实体将为拥有方定义一个字段,为关系的映射方定义另一个字段。