sql - 与 JPA 的 friend 关系

标签 sql hibernate jpa

我很难创建关系的最佳 JPA 表示。似乎有很多方法可以做到这一点,但我不确定哪种方法是最佳的。如果没有 JPA,我可能会将结构表示为 PERSON 表和 FRIEND 表。假设 PERSON 表只有一个 ID 和 NAME。 FRIEND 表有一个 OWNER_ID、一个 PERSON_ID 和一个可设置的 bool IS_ACTIVE 字段。 OWNER_ID 和 PERSON_ID 都引用 PERSON 表。一个人可以有很多 friend ,所以唯一的主键将在 OWNER_ID 和 PERSON_ID 上。在我的代码中,我希望 PersonEntity 控制这种关系。 Java 中的操作可能如下所示:

person1.getFriends().add( new Friend( person2, isActive ) );
Friend friend = person1.findFriend( person2ID );

类似的东西。请注意,我希望 JPA 隐式分配 friend 关系的所有者。在上面的代码中,我没有在 Friend 构造函数中传递它,我只传递了复合键的 PERSON 部分。

这是我的第一个猜测:

@Entity
public class Person {
   @Id
   @GeneratedValue
   private Long id;

    @OneToMany( mappedBy="key.owner", cascade=CascadeType.ALL, orphanRemoval = true)
    private Set<Friend> friends = new HashSet<>();

    // getter and setter for Friends
    ...
}

@Entity
public class Friend {
   @EmbeddedId
   private Key key = new Key();

   private boolean isActive;

   ...

   @Embeddable
   public static class Key implements Serializable {
      @ManyToOne
      private Person owner;

      @OneToOne
      private Person person;

      ...
   }
}

但是当我使用这段代码时,我得到了堆栈溢出错误。我假设它被 OneToOne 关系搞糊涂了。

在 JPA 2.0 中为这种关系建模的最佳方式是什么?我想最简单的事情是在 Friend 中引入一个生成的长 key 。但这似乎会使“find friends for john”的查询变得更加复杂,因为我将引入第三个映射表,基本上在 SQL 中映射关系两次。另一种方法是使其成为单向的 OneToMany 关系,甚至不在 Friend 中明确指定 OWNER。这将为映射引入另一个表并使查询有点复杂。使用 ElementCollection 而不是 OneToMany 似乎很简单,但我的理解是我无法将 Friend 作为一个实体来管理?

如果你们需要更多细节或要求,请告诉我。顺便说一句,我尝试将 MapsId 放在 Friend 中作为 PKEY 的所有者部分,但这给了我运行时错误。

感谢任何帮助。

注意:即使我将生成的 key 添加到 Friend,我也想强制 Friend 实体中 {owner,person} 组合的唯一性。

最佳答案

我确实会向 Friend 实体添加一个自动生成的 ID。它会使事情变得更简单(没有包含关联的复合键)。我看不出添加这样一个 ID(并因此在 Friend 表中增加这样一个列)会使任何查询变得更加复杂,或者引入一个新表。它不会。您只需多一个列,作为 friend 表的主键。

完成后,您需要修复映射:

  1. Friend 和 Person 之间的关联不是 OneToOne,而是 ManyToOne,因为几个人可以成为另一个人的 friend 。
  2. mappedBy 应该保存另一个实体中的字段名称,它表示关联的另一端。在您的情况下,它因此是“key.owner”。如果您停止使用复合键,它将只是“所有者”。

最后,在双向 OneToMany 关联中,所有者始终是多方(即本例中的 friend )。所以你必须初始化 friend.owner 字段以保持关联。但是,如果您封装 friend 列表而不是让它从外部访问,那么事情就会很简单。而不是做

person1.getFriends().add( new Friend( person2, isActive ) );

简单地做

person1.addFriend( new Friend( person2, isActive ) );

并确保 addFriend() 方法包含以下指令:

friendToAdd.setOwner(this);

关于sql - 与 JPA 的 friend 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14633798/

相关文章:

java - Oracle 中的 JPA 和 Flyway boolean 类型

java - 使用 jpa 进行多次更新

sql - 在 SSIS 中编写自定义日志提供程序

sql - PostgreSQL - 选择条件满足的不同(列1,列2)

java - 如何跟踪 Java Web 应用程序中的连接池 - DBMS_APPLICATION_INFO

java - LocalDate.MAX 无法持久保存在 Oracle 数据库中

mysql - NetBeans 6.7 Beta - 为什么它认为某些表没有主键?

sql - 查询中的 Oracle 和 SQLServer 函数评估

php - SQL Server PDO UPDATE 循环错误

java - Hibernate, MySQL - 数据截断 : Data too long for column exception message