【问题标题】:PSQLException: ERROR: Duplicate key value violates uniqueness constraintPSQLException:错误:重复键值违反唯一性约束
【发布时间】:2022-01-27 15:31:19
【问题描述】:

我有两张桌子

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "car")
public class CarEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    private String name;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "manufacture_id")
    private ManufactureEntity manufactureEntity;
}   

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "manufacture")
public class ManufactureEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}

制造商表中已经有一个名为 AUDI 的条目。 当我尝试创建新记录时

ManufactureEntity manufactureEntity = new ManufactureEntity();
manufactureEntity.setName("AUDI");
CarEntity car = new CarEntity();
car.setName("a6");
car.setManufactureEntity(manufactureEntity);
carService.create(car);

然后我得到一个错误,这样的记录已经存在

org.postgresql.util.PSQLException: ERROR: Duplicate key value violates the "manufacture_name_key" uniqueness constraint
Details: The key "(name)=(AUDI)" already exists.

事实证明,对该函数的调用正试图向制造表添加一个新条目。 如何仅在不存在时才创建此记录,并且如果这样的记录已经存在,那么只需为manufacturer_id字段分配制造表中的键值?

  1. 添加新 CarEntity 记录时,如何指定其制造商实体字段将分配给制造商“AUDI”表中的现有记录?
  2. 但如果制造表中没有“AUDI”条目,则需要创建它。

还是不能同时实现?但只有一点。

还是我误解了 OneToOne 注释?汽车“a6”表中的一项仅对应于制造商“AUDI”表中的一项。让我们继续。汽车“a8”表中的一项仅对应于制造商“AUDI”表中的一项。还是我错了?而这里需要实现ManyToOne。

如果我将 OneToOne 注释更改为 ManyToOne,我会得到同样的错误

The key "(name)=(AUDI)" already exists.

如果我改变 CascadeType

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)

添加到汽车表有效,但如果没有这样的记录,添加到制造表不起作用。 IE。当我指定特定制造商时

manufactureEntity.setId(1L);

然后写入汽车表不会出错。 但是如果我指定一个未知的制造商

manufacture Entity.setName("AUDIM");

然后我得到错误

NULL value in the "manufacture_id" column

使用 CascadeType.ALL 注解,只有在制造表中没有这样的记录时才起作用,如果有则不起作用。 使用 CascadeType.MERGE 注解,只有在制造表中有这样的条目时才有效,如果没有,则无效。

问题仍然悬而未决。 如何使汽车表中的条目和制造表中的条目起作用? 还是根本不可能,我需要先手动检查制造表中的现有记录,如果不存在,则添加它,然后写入汽车表?

【问题讨论】:

    标签: spring-data-jpa


    【解决方案1】:

    您的问题似乎与尝试在name 的列中添加新名称“AUDI”有关。由于此列包含unique 的属性,因此整个列中只能有一个“AUDI”,这意味着即使id 发生变化,也无法添加新的“AUDI”值。

    如果您仍然希望能够将相同的值添加到 name 的列(这似乎是您想要的),您可以通过从表中删除该列并添加一个不带唯一约束。或者干脆从表中删除约束。

    Remove uniqueness of index in PostgreSQL

    【讨论】:

    • 制造商表中的字段必须是唯一的。我不明白如何正确地将条目添加到汽车表?制造商表中应该只有一个 AUDI 条目
    • 即使manufacturer 表有一个唯一的名称(只能有一个AUDI),在car 表中你可以有多个AUDI。因此,保留制造商表中的唯一性,但删除汽车表中的唯一性约束。这样,您就可以拥有来自同一制造商 (AUDI) 的多辆汽车
    • 但是我对 car 表中的 producer_id 字段没有唯一性约束。由于在制造表中创建了另一条记录而发生错误
    • 那我觉得你们的关系不应该是OneToOne。当使用 OneToOne 关系时,这意味着对于每条记录,只能有一条记录到另一个表中的列。因此,您不能有两行制造商。尝试使用 ManyToOne(许多汽车到一个制造商),看看它是否有效
    • 等等。为什么你认为我违反了这条规则?汽车“a6”表中的一项仅对应于制造商“AUDI”表中的一项。让我们继续。汽车“a8”表中的一项仅对应于制造商“AUDI”表中的一项。还是我错了?而这里需要实现ManyToOne。
    猜你喜欢
    • 2020-02-15
    • 2016-07-27
    • 2011-10-17
    • 2012-03-03
    • 2018-08-26
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    相关资源
    最近更新 更多