我在 MySQL 数据库上使用 spring-boot 和 spring-data-jpa 以及 hibernate。
我已经定义了一个像这样的实体-
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@IdClass(TestTableId.class)
@Builder
@Table(name = "test_table")
public class TestTable implements Serializable, Persistable<TestTableId> {
private static final long serialVersionUID = 150967283000000000L;
@Id
private String idCol1;
@Id
private String idCol2;
@Id
private String idCol3;
@CreationTimestamp
@Column(name = "insert_time", columnDefinition = "DEFAULT CURRENT_TIMESTAMP(6)")
@Temporal(TemporalType.TIMESTAMP)
private Date insertTime;
// other columns
@Override
public boolean isNew() {
return true;
}
@Override
public TestTableId getId() {
return new TestTableId(idCol1, idCol2, idCol3);
}
}
我的
IdClass
定义如下-
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@EqualsAndHashCode
public class TestTableId implements Serializable {
private static final long serialVersionUID = -6903451981600000000L;
private String idCol1;
private String idCol2;
private String idCol3;
}
我正在尝试
INSERT
TestTable
实例列表,并且还为所有 idCol1
、idCol2
和 idCol3
提供值,因为这些 id 列都是在应用程序中生成的。
以下是我用来保存实体的方法-
@Transactional
public List<TestTable> saveTestTable(List<TestTable> records) {
return testTableRepository.saveAll(records);
}
运行时,它会在数据库上触发
INSERT
和 UPDATE
查询。我怎样才能避免这种情况,因为只有 INSERT
查询才能完成这项工作?
蒂亚!
您遇到的行为(Hibernate 对新创建的实体同时发出 INSERT 和 UPDATE 语句)可能是由于您在实体类中实现 isNew() 方法的方式造成的。具体来说,您的 TestTable 类始终为 isNew() 方法返回 true。此方法旨在通知 Spring Data JPA 实体是否应被视为新实体(因此需要插入)或现有实体(因此需要更新)。始终返回 true 会导致 Spring Data JPA 将每个保存操作视为正在处理一个新实体,即使它已经被持久化。
在您的情况下,由于 idCol1、idCol2 和 idCol3 是应用程序生成的标识符,因此您需要一种可靠的方法来确定实体实例是否真正是新的,或者它是否代表数据库中预先存在的记录。一种常见的方法是检查标识符字段是否为空或是否具有某些默认未设置值,用于指示新的未保存实体。但是,由于您的标识符是在应用程序中生成的,并且可能始终在保存之前设置,因此您需要不同的策略。