JPA 中的自引用字段映射

发布于 2024-12-22 11:31:31 字数 253 浏览 4 评论 0原文

假设我们有 User 实体类。用户可以与其他用户成为朋友。如何映射此自引用集合字段而不创建名为“连接”的新实体或在数据库中创建多个条目?

@Entity
public class User {
...
@ManyToMany
private Collection<User> friends;
...
}

USER_ID-FRIEND_ID
1 - 2
2 - 1 (duplicate... I don't need it)

Lets say we have User entity class. User can be friends with other users. How can i map this self-reference collection field without creating a new entity called Connection or creating multiple entries in the database?

@Entity
public class User {
...
@ManyToMany
private Collection<User> friends;
...
}

USER_ID-FRIEND_ID
1 - 2
2 - 1 (duplicate... I don't need it)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

醉生梦死 2024-12-29 11:31:31

以下是我的 ElementEntity 代码的快照:

@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private List<ElementEntity> children;

@JoinColumn(name = "ParentId", referencedColumnName = "ElementId")
@ManyToOne(fetch = FetchType.LAZY)
private ElementEntity parent;

数据库上有字段:

  • ElementId - 主键;
  • ParentId 与父级的关系

Following is snapshot from my code for ElementEntity:

@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
private List<ElementEntity> children;

@JoinColumn(name = "ParentId", referencedColumnName = "ElementId")
@ManyToOne(fetch = FetchType.LAZY)
private ElementEntity parent;

Where on database there are fields:

  • ElementId - primary key;
  • ParentId relation with parent
岁月蹉跎了容颜 2024-12-29 11:31:31

你不能——你需要数据库中的两条记录。

实际上,对于友谊关系,我认为像 Neo4j 这样的图形数据库是正确的选择。在那里,您有两个用户,只需添加一个边缘“朋友”即可。

You can't - you need both records in the database.

Actually, for friendship relations, I'd say that a graph database like neo4j is the proper thing to use. There you have the two users and simply add an edge "friends".

南风起 2024-12-29 11:31:31

至少您需要一个关系表

所以你有一个USER表和一个FRIENDS

user_id friend_id
   1      2

但是@Bozho的答案比我的(neo4j)好得多。

At least you will need a relational table.

So you have a USER table and a FRIENDS:

user_id friend_id
   1      2

But @Bozho answer is way better than mine (neo4j).

旧夏天 2024-12-29 11:31:31

嗯,事实上你可以。

您可以使用 @PreUpdate、@PrePersists、@PostUpdate 等注释来手动转换集合的元素。这样您的实体就可以按照您想要的方式呈现它们,而在数据库中您只存储原始文本。

更可行的替代方案是使用 @Convert 注释,自 jpa 2.1 起可用(hibernate 中的 @UserType)。它告诉 jpa 每次在数据库中读取/保存时将字段转换为另一种类型。
为此,您应该使用@Convert注释,指定AttributeConverter对象。

例如

    public class Parent {
      @Id
      private Integer id;

      @Convert(converter = FriendConverter.class)
      private Set<Parent>friends;
    }

,转换器类如下所示:

    @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;
      }
    }

它是一个虚拟实现,但它为您提供了想法。

作为个人评论,我确实建议按照应有的方式绘制关系图。将来它将避免您遇到问题。使用枚举时 AttributeConverter 会派上用场

Well, in fact you can.

You can use annotations like @PreUpdate, @PrePersists, @PostUpdate and so to convert manually the elements of a collection. This way your entity can render then them way you want while in database you only store a raw text.

A more pausible alternative will be to use @Convert annotation, available since jpa 2.1 (@UserType in hibernate). It tells jpa to convert the field into another type everytime it read/save in database.
For it you should use @Convert anotation, specifying and AttributeConverter object.

For example

    public class Parent {
      @Id
      private Integer id;

      @Convert(converter = FriendConverter.class)
      private Set<Parent>friends;
    }

And converter class like the following:

    @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;
      }
    }

It is a dummy implementation but it gives you the idea.

As a personal comment, I do recommend to map the relationship as it should. In the future it will avoid you problems. AttributeConverter comes in handy when working with enums

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文