【问题标题】:JPA Entity best way for ManyToOne Bidirectional Relationship with Foreign KeyJPA Entity 与外键的多对一双向关系的最佳方式
【发布时间】:2020-11-20 13:53:24
【问题描述】:

考虑下表结构和关系。

Teacher
id(pk),
tname,
subject_id(fk),
subject_name

Subject
sid(pk),
sname,
subject_learning_curve

TEACHER(关系所有者)到 SUBJECT 多对一,双向关系

我在 intellij 中使用了持久化工具窗口here。它基于数据源自动为数据库中的所有关系生成实体。

在实体中是这样生成的

@Entity
//using lombok for getters and setters
public class TEACHER{
     
    @Id
    @GeneratedValue
    private Long id;
    private String tname;
    private long subject_id;
    private String subject_name;

    @ManyToOne
    @JoinColumn(name = "subject_id",referencedColumnName="sid")
    private Subject subjectBySid;    //is this fine to have a reference like this
}

或下面的第二种方法

@Entity
    //using lombok for getters and setters
    public class Teacher{
         
        @Id
        @GeneratedValue
        private Long id;
        private String tname;
        @ManyToOne
        @JoinColumn(name = "subject_id",referencedColumnName="sid")
        private Subject subject;    //or just this it will suffice all use case,like if i just want to read Teacher data and just the sid not the whole subject row
    }

同样,Subject 也会有指向 Teacher 表的参考。

根据以下几点,有人可以提供见解。

  1. 以上两种写实体的方式中哪一种是理想且正确的。
  2. 从 Hibernate 和 JPA 的角度来看哪个更有效。
  3. 根据我选择编写实体的方法生成的 sql 会有什么不同吗?
  4. 如果我采用第二种方法,查询记录并将其保存到数据库或检索会更容易。
  5. 当我在 Entity 中获取数据时,TEACHER 中的 subject_id 是否有价值,或者它只是一个名为 subject 的引用,我不会在 TEACHER.subject_id 或@JoinColumn(name = "subject_id",referencedColumnName="sid") 注释中获取该特定字段,并且它应该在 TEACHER.subject_id 中具有价值

【问题讨论】:

  • 只是为了澄清。您确定要将TeacherSubject 映射为多对一,反之亦然吗?通常Teacher会讲几门课。
  • 是的,这只是例如背后没有特定的逻辑。您可以想到任何多对一关系,多方是关系的所有者。
  • 还有更多的浏览量吗?
  • 我肯定会选择第二种方法——坦率地说,我从未在任何项目中见过第一种方法。第一个包含冗余信息,(它违反了 DB 标准形式之一——我认为是 2NF)。如果您采用第一种方法,您将不得不同步冗余数据 - 没有意义。首先,使用两个单独的表/实体更自然,从性能的角度来看,您不会丢失任何东西,因为您将在 subject 表中的 teacher 外键上拥有索引。

标签: java database hibernate jpa spring-data-jpa


【解决方案1】:

以下是我对您的问题的回答和建议:

1.以上两种写实体的方式中哪一种比较理想和正确。

方法 2 是编写实体的正确方法。一旦定义了 @ManyToOne 与另一个实体的关系,就无需定义特定于该实体的列。

2.从 Hibernate 和 JPA 的角度来看哪个更高效。

JPA 是 Java 中关系数据管理的规范,Hibernate 是将对象的状态保存到 DB 中的对象关系映射 (ORM) 工具。简单来说,Hibernate 就是 JPA 的实现。因此,比较它们不应该是一个问题。您可以将 Hibernate 与其他可与 Spring 框架(如 iBatis、EclipseLink 等)一起使用的 ORM 工具进行比较。

3.根据我选择编写实体的方法生成的 sql 会有什么不同吗?

不,生成的 SQL 将是相同的。但是,要生成该 SQL,您可以使用不同的方法,例如 @NativeSqlQueryHibernate Query Language(HQL) 等。

4.如果我采用第二种方法,查询记录并将其保存到数据库或检索会更容易。

您绝对应该使用第二种方法来实现清晰、直接和相关的方法。如果您考虑面向对象语言和关系数据库管理的原则,则第一种方法的核心是错误的。当您可以通过映射轻松链接它们时,无需创建额外的列、代码、实体属性和其他错误。

5. 当我在 Entity 中获取数据时,TEACHER 中的 subject_id 是否有价值,或者它只是一个名为 subject 的引用,我不会在 TEACHER.subject_id 或 @JoinColumn(name = "subject_id",referencedColumnName="sid") 注释会解决这个问题,它应该在 TEACHER.subject_id 中具有价值

在您的数据库中,您的Teacher 表中应该有一个列subject_id,该列将是一个外键,并引用Subject 表的sid 列。这发生在数据库端。
在面向对象端(Spring),您可以使用 Subject 的创建对象引用与 Student 进行映射,或者您可以直接在 HQL 或 NativeQuery 中使用字段 subject_id 来执行 DB操作和持久化数据。 因此,您将在 Teacher 实体中获得 subject_id

【讨论】:

  • 我不是说 hibernate vs jpa,我的意思是当我查询 @Repositoryclass 或者当我将数据插入到任何这些表中时,我需要编写代码,这主要取决于我有@Entity,这是JPA。因此,根据我编写@Entity 的方式,它可以让我编写或多或少的代码。然后是 Hibernate,它将生成相同的查询
  • 好的,在这种情况下,方法 2 更有效,因为不需要声明新属性,编写它们的 getter/setter 并将它们持久保存在与主题相关的字段中,比如你有的 subject_id 和 subject_name已将 Teacher 实体映射到 subject 实体。
  • 我已经编辑了我的答案。如果答案对帮助我在社区中成长有用,请投票并接受。如果您需要一个示例来了解如何使用实体以及subject_id 获取和操作关系,请告诉我。
  • Hence, you will get subject_id in your Teacher entity 我可以理解,如果我提到学生,我显然会在该参考中包含学生 ID,但我想弄清楚我是否会在教师 JPA 中获得 TEACHER.subject_id 作为字段实体
  • 是的,您将获得subject_idTeacher 实体。要确认这一点,请检查您相应的数据库表。您将找到该列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多