Postgresql 如果我对PK使用约束会发生什么?
如果我有一个PK,并对其进行了限制,会发生什么。 我知道,当我尝试在DB中写入同一个实体时,它将覆盖它,而不是由于约束而产生冲突。 问题是为什么? 它会覆盖它,因为它是用hibernates(spring数据jpa)编写的,方法是jpaRepository.save()。因此,如果实体具有相同的主键,并且所有其他列都相同,那么它会覆盖实体 即使在以下情况下也会发生这种情况: 我对3个VARCHAR列有一个约束:(名称、版本、类型) 我有一个由3个varchar组成的PK:name\u version\u type 创建模式时,sql文件中的spring和flyway会发生以下情况:Postgresql 如果我对PK使用约束会发生什么?,postgresql,constraints,Postgresql,Constraints,如果我有一个PK,并对其进行了限制,会发生什么。 我知道,当我尝试在DB中写入同一个实体时,它将覆盖它,而不是由于约束而产生冲突。 问题是为什么? 它会覆盖它,因为它是用hibernates(spring数据jpa)编写的,方法是jpaRepository.save()。因此,如果实体具有相同的主键,并且所有其他列都相同,那么它会覆盖实体 即使在以下情况下也会发生这种情况: 我对3个VARCHAR列有一个约束:(名称、版本、类型) 我有一个由3个varchar组成的PK:name\u versi
CREATE TABLE package
(
id surrogate_id PRIMARY KEY,
CONSTRAINT uq_package_name_version_type UNIQUE(surrogate_id),
name VARCHAR NOT NULL,
version VARCHAR NOT NULL,
type VARCHAR NOT NULL
)
;
public static final String hash(String name, String version, String type)
{
return new StringBuilder().append(name)
.append("_").append(version)
.append("_").append(type)
.toString();
}
这就是java中使用Hibernate时发生的情况:
@Table(name = PackageEntity.TABLE_NAME, uniqueConstraints = {
@UniqueConstraint(columnNames = {"package"}, name = ConstraintName.SURROGATE_ID)})
各栏:
@NotNull
private String name;
@NotNull
private String version;
@NotNull
private String type;
@Id
@Column(name = "surrogate_id")
private String surrogateId;
以及如何创建代理id:
CREATE TABLE package
(
id surrogate_id PRIMARY KEY,
CONSTRAINT uq_package_name_version_type UNIQUE(surrogate_id),
name VARCHAR NOT NULL,
version VARCHAR NOT NULL,
type VARCHAR NOT NULL
)
;
public static final String hash(String name, String version, String type)
{
return new StringBuilder().append(name)
.append("_").append(version)
.append("_").append(type)
.toString();
}
我希望它看到相同的PK并试图覆盖实体,但我也希望停止事务,因为它在3列上看到冲突。这不会发生。它只考虑PK。为什么?允许但多余地在主键上添加
UNIQUE
约束,因为主键意味着唯一性
您应该删除额外的约束,因为它会导致创建额外的索引,这将浪费空间并减慢数据修改的速度。允许但多余地在主键上添加
唯一
约束,因为主键意味着唯一性
您应该删除额外的约束,因为它会导致创建额外的索引,这将浪费空间并减慢数据修改的速度。在spring
JpaRepository
中,默认情况下,保存操作如下所示:
如果实体没有设置主键(带有@Id
注释的字段),则使用INSERT
SQL语句在数据库中创建新记录
如果实体确实有主键-则使用UPDATE
SQL语句修改现有记录
因此,在您的情况下,spring认为您正在更新现有实体,并且没有发生插入,因此不会发生冲突。这就是为什么约束是无用的
为了克服这个问题,您可以实现接口和isNew
方法,专门让spring知道您正在插入一个新实体。在这种情况下,spring将执行插入操作,而不进行更新。在springJpaRepository
中,默认情况下,保存操作如下所示:
如果实体没有设置主键(带有@Id
注释的字段),则使用INSERT
SQL语句在数据库中创建新记录
如果实体确实有主键-则使用UPDATE
SQL语句修改现有记录
因此,在您的情况下,spring认为您正在更新现有实体,并且没有发生插入,因此不会发生冲突。这就是为什么约束是无用的
为了克服这个问题,您可以实现接口和isNew
方法,专门让spring知道您正在插入一个新实体。在这种情况下,spring将执行insert而不是update。当您有一个主键并尝试插入具有相同主键的行时,它不会更新它(除非您使用UPSERT)。它抛出了一个重复键的错误,并且看不到任何其他构造。如果无法插入行,则查看其他内容是没有意义的。如果您有一个PK并尝试插入具有相同PK的行,则不会更新该PK(除非您使用UPSERT)。它会抛出一个重复键错误,并且不会查看任何其他解释。如果无法插入行,则查看其他任何内容都没有意义。您可以(通过单击下面的链接)提问吗并添加CREATE TABLE
语句,包括您创建的所有约束,谢谢,先生!我现在就知道了。谢谢,先生!我现在就知道了。所以考虑到@Roman Konova的回答,这意味着它进行了更新,但没有约束,因为约束由于PK而被忽略,对吗?不,唯一的约束Is在更新过程中被选中,因为它由唯一索引支持。因此,您需要付出两次唯一性检查(和两次索引修改)的代价,但您没有任何好处,因为主键已经保证了唯一性。因此,考虑到@Roman Konova的回答,这意味着它进行了更新,但没有约束,因为约束由于PK而被忽略,对吗?不,在更新过程中检查唯一约束,因为它有唯一的i因此,您需要付出两次唯一性检查(和两次索引修改!)的代价,但您没有任何好处,因为主键已经保证了唯一性。