【问题标题】:Correct way to check for foreign key constraint violation in Hibernate?在 Hibernate 中检查外键约束违规的正确方法?
【发布时间】:2020-09-20 03:26:56
【问题描述】:

我有两个表已经存在于 postgres 中,让我们调用表 A 和表 B。表 B 的一列有一个外键约束,因为它必须是表 A 的主键。因此有很多B 和 A 的一对一关系,表 B 中的多条记录对应表 A 的一条记录。

这两个表的实体定义如下。

public class TableA implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long userId;

@Column(name = "name")
private String name;

@Column(name = "email")
private String email;

@Column(name = "phone_number")
private String phoneNumber;
}

TableB的实体定义如下:

public class Shots implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "item_id")
private Long itemId;

@Column(name = "user_id")
private Long userId;
}

其中 userId 是表 A 中主键 user_id 的外键映射。 这些约束已经在底层的 postgres 数据库中定义了,所以我没有考虑使用 @ManyToOne 注释关系(仍然试图绕开它)。

我目前处理外键约束违反情况的方法是执行以下操作:

try {
        tableBrepository.save(newShot);
    } catch (ConstraintViolationException ex) {
        logger.error("Violating foreign key constraint" + ex.getMessage());
    }

我的问题是,有没有更好的方法来检查这种违规行为?我可以做些什么来更好地构建 Spring Data JPA 中的外键约束?

【问题讨论】:

  • 您可以使用@OneToMany进行映射并在之前获取以检查是否存在或抛出异常vladmihalcea.com/…
  • 不使用映射的唯一其他方法是使用附加查询验证对象是否在数据库中。现在它需要额外的查询来验证,但我认为当你处理 ID 时,你不能信任客户端并且总是必须验证。您的方法的问题是当有多个这样的字段并且想要返回特定错误时。即使使用映射,您也需要获取对象,因此需要额外的查询。

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


【解决方案1】:

因此B和A之间存在多对一的关系,表B中的多条记录对应表A的一条记录。

JPA 实体中的这类东西是用@ManyToOne 注释处理的。您通常不直接引用任何 id 字段,而是告诉 JPA 应该有什么。所以在你的班级 TableB (或者我应该称之为...镜头?)应该是这样的:

@ManyToOne
private TableA tableA;

// and get rid of this
// @Column(name = "user_id")
// private Long userId;

并且可选 - 所以不一定 - 你可以在你的 TableA 中拥有:

@OneToMany
private List<TableB> tableBsOrShouldICallYouShots;

我不确定您的实际问题是什么,但是直接设置和引用 id 字段时可能会导致您遇到困难。

现在,如果您 - 例如 - 使用存储库找到一些 TableB,那么之后您就可以这样做了

tableB.getTableA()

在保存之前你会这样做:

tableB.setTableA(somSortOftableA);
// so not tableB.setUserId(someLongIdFOrtableA);

现在的重点是引用完整性没有问题,因为您不需要知道任何 ID,也不能设置任何错误的 ID。除非您在将 TableA 设置为 TableB 之前首先需要通过 id 获取 TableA,但在这种情况下,您仍然不会设置任何 ID。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-02
    • 2014-12-09
    • 1970-01-01
    • 2014-03-17
    • 2011-04-19
    • 1970-01-01
    • 2018-06-28
    • 2012-07-15
    相关资源
    最近更新 更多