【问题标题】:How to set Id of one entity to the Id of another entity using JPA?如何使用 JPA 将一个实体的 ID 设置为另一个实体的 ID?
【发布时间】:2022-07-20 11:48:33
【问题描述】:

我是 Spring Boot 的 JPA 概念的新手,因此需要您的帮助来决定如何将另一个实体的 ID 导入到 HealthData 实体中,例如 User。以下是我的User 实体:

@Entity
@Table(name = "user",uniqueConstraints = {@UniqueConstraint(columnNames = "email")})
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;
    @Email
    @Column(nullable = false)
    private String email;

    private String imageUrl;
    @Column(nullable = false)
    private Boolean emailVerified=false;
    @JsonIgnore
    private String password;
    @NonNull
    @Enumerated(EnumType.STRING)
    private AuthProvider authProvider;
    private String providerId;
}

我希望以下列方式定义HealthData 实体:

@Entity
@Table(name = "HealthData",uniqueConstraints = {@UniqueConstraint(columnNames = "id")})
public class HealthData {
    @Id
    private Long id; //how to import id of User here?

    @Column
    private Double height;
    @Column
    private Double weight;
    @Column
    private int age;
    ...other columns

}

现在,我希望将User 中的Id 用于该实体(一种建立父子关系的方式)。我不想在 HealthData 中添加 User 类对象。我曾想过在HealthData 中使用@OneToOne,但随后会在其中添加User。我怎样才能在子表中包含父表中的 Id?

【问题讨论】:

  • 为什么要这样做?这就是 ORM 的工作方式。如果你不想要它,你应该考虑使用普通的 JDBC 或像 MyBatis 这样的轻量级映射器。
  • 这似乎是要走的路,因为它会限制加载不必要的对象以优化性能。我刚开始使用 Spring Boot 和 JPA。所以我认为只导入 Key 而不是整个对象会非常有效。
  • 您的建议是导入整个User 对象并让HealthData 生成独立于User's id 的自己的ID?
  • 您应该了解有关 JPA 实现的更多信息。您通常可以控制相关对象的加载方式。看这里以获得一个想法:baeldung.com/hibernate-lazy-eager-loading。但是你应该非常小心。这取决于使用情况,哪种获取类型是合适的。你可能会遇到N +1 select problem
  • 使用 ORM 时,最直接的过程是为每个表设置单独的 ID。即使在纯 SQL 中,您也不会在多个表中重用相同的 ID 来建模一对一的关系。这种耦合太紧了。您总是会在一个表中使用一个单独的字段,并使用指向另一个表 ID 的外键。

标签: java jpa spring-data-jpa


【解决方案1】:

在这种情况下,您的 HealthData 引用了 User,我不确定您为什么不将其映射为外键。如果你能做到,我建议如下:

@Entity
@Table(name = "HealthData")
public class HealthData {
    @Id
    @OneToOne
    @JoinColumn(name = "id")
    private User user; 

    @Column
    private Double height;
    @Column
    private Double weight;
    @Column
    private int age;
    ...other columns
}

JPA 然后为您处理将“ID”设置为您的用户实例中的值,并且可以自动将两者保留在同一事务中。允许将引用标记为 ID 被称为派生 ID,我相信自 JPA 2.0 起就受支持。

至于效率,您仍然可以延迟获取甚至不获取用户实例。使用稍微不同的方法将 ID 列映射为基本列很简单:

@Entity
@Table(name = "HealthData")
public class HealthData {
    @Id
    private Long id;
    
    @MapsId
    @OneToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "id")
    private User user; 

    @Column
    private Double height;
    @Column
    private Double weight;
    @Column
    private int age;
    ...other columns
}

当您设置 healthData.user 参考时,JPA 将根据它为用户 ID 序列生成的内容来设置用户 ID 和 healthData.id 值。

【讨论】:

    【解决方案2】:

    可以使用getter和setter来设置healthdata表中用户id的值

    【讨论】:

      猜你喜欢
      • 2010-10-28
      • 2014-03-29
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      • 2011-07-16
      • 1970-01-01
      • 2012-03-27
      • 1970-01-01
      相关资源
      最近更新 更多