Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA中的自参考场映射_Java_Jpa_Eclipselink - Fatal编程技术网

Java JPA中的自参考场映射

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) @实体 公共类用户{ ... @许多 私人收

假设我们有用户实体类。用户可以与其他用户成为朋友。在不创建名为Connection的新实体或在数据库中创建多个条目的情况下,如何映射此自引用集合字段

@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注释进行映射。与所有多对多关系一样,必须定义一个桥接表来存储关系的双方。实体将为拥有方定义一个字段,为关系的映射方定义另一个字段。