我有一个 Oracle 数据库表,其中的列位于我的 FoobarId 类中。FooarId 中的所有 3 个字段都是我的 Foobar 表中的复合 pk。
我在第一次运行时插入数据正常。但是当我再次运行它时,我得到了一个 ORA-00001:违反了我的 PK 的唯一约束。我在其他项目中也有类似的代码,运行良好。这似乎没有更新记录,而是尝试再次插入。我的embeddedId有问题吗?
我的实体类:
@Entity
@Table(name = "FOOBAR_TABLE")
public class Foobar implements Serializable {
private static final long serialVersionUID = 4290109857781985996L;
private FoobarId foobarId;
private int containerId;
private String containerType;
private String action;
public Foobar() { }
public Foobar(String itemName, int itemId, Date itemDate) {
foobarId = new FoobarId(itemName, itemId, itemDate);
}
@EmbeddedId
public FoobarId getFoobarId() {
return foobarId;
}
public void setFoobarId(FoobarId foobarId) {
this.foobarId = foobarId;
}
// getters and settters
}
我的 ID 类别:
@Embeddable
public class FoobarId implements Serializable{
private static final long serialVersionUID = 7393136028821250311L;
private int itemId;
private String itemName;
private Date itemDate;
public FoobarId(){}
public FoobarId(String itemName, int itemId, Date itemDate) {
super();
this.itemId = itemId;
this.itemName = itemName;
this.itemDate = itemDate;
}
// getters/setters
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((itemDate == null) ? 0 : itemDate.hashCode());
result = prime * result + ((itemName == null) ? 0 : itemName.hashCode());
result = prime * result + itemId;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
FoobarId other = (FoobarId) obj;
if (itemDate == null) {
if (other.itemDate != null) {
return false;
}
} else if (!itemDate.equals(other.itemDate)) {
return false;
}
if (itemName == null) {
if (other.itemName != null) {
return false;
}
} else if (!itemName.equals(other.itemName)) {
return false;
}
if (itemId != other.itemId) {
return false;
}
return true;
}
}
我有必要的 Repository 接口(interface),它扩展了 CrudRepository。
在我的服务类中,我保存了 Foobar 项目的列表:
@Transactional
public void addList(List<Activity> itemList) {
logger.info("Saving Activity List size of: " + itemList.size());
activityRepository.save(itemList);
}
创建表sql:
CREATE TABLE "FOOBAR"
(
"ITEM_NAME" VARCHAR2(50 CHAR) NOT NULL ENABLE,
"ITEM_ID" NUMBER NOT NULL ENABLE,
"ITEM_DATE" DATE NOT NULL ENABLE,
"CONTAINER_ID" NUMBER,
"CONTAINER_TYPE" VARCHAR2(50 CHAR),
"ACTION" VARCHAR2(50 CHAR),
CONSTRAINT "FOOBAR_PK" PRIMARY KEY ("ITEM_NAME", "ITEM_ID", "ITEM_DATE")
)
最佳答案
“日期”很棘手,因为语义取决于上下文。例如,java.util.Date
包含毫秒精度的时间,但 Oracle 的 SQL DATE
数据类型表示日期和时间,精度高达一秒。如果您的 Java 代码在具有 SQL DATE
数据类型的 PRIMARY KEY 列上使用 java.util.Date
的相等语义,您将看到唯一值(来自JPA 观点)在只有几分之一秒的时间有所不同的情况下,任何时候都会违反 UNIQUE CONSTRAINT 持久化到数据库中。
正如您所观察到的,将数据库中的列数据类型更改为TIMESTAMP
将提高列的时间分辨率以及您的键空间,从而解决问题。
关于java - 第二眼 JPA 保存列表导致 PK 违规,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55602457/