java - 第二眼 JPA 保存列表导致 PK 违规

标签 java spring-data-jpa

我有一个 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/

相关文章:

java - Spring Data REST repository 时不时404

spring-boot - Elasticsearch Spring boot findAll Result窗口太大,from + size必须小于或等于:[10000]但为[331576]

java - spring boot jpa - 创建定义名称为 'entityManagerFactory' 的 bean 时出错

java - STGroupDir 的字符串模板 4 问题

java - 如何使用 com.strobel.decompiler.PlainTextOutput 在控制台中打印

java - JAVA中如何通过IP地址获取时区

java - 如何在 Spring JPA 中更新 EmbeddedID 的字段

java - 如何使用 Spring Data JPA 查询 map 值?

java - 运行 Tomcat 服务器 Intellij 跳过测试类

java - 对于给定的 Date 对象,捕获其与 GMT 时区相关的值