gpt4 book ai didi

更新实体时出现 java.sql.SQLIntegrityConstraintViolationException

转载 作者:行者123 更新时间:2023-12-04 20:13:43 24 4
gpt4 key购买 nike

我是 JPA 的新手,遇到以下问题,可能是因为对级联和关联的理解不够?我有两个处于双向 OneToMany - ManyToOne 关联中的实体:

@Entity
public class TestRun implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

public Long getId() {
return id;
}

public TestRun(){

}

public void setId(Long id) {
this.id = id;
}

@ManyToOne(optional=false, cascade={CascadeType.PERSIST, CascadeType.MERGE})
private Test performedTest;

public Test getPerformedTest() {
return performedTest;
}

public void setPerformedTest(Test performedTest) {
this.performedTest = performedTest;
}
.....

@Override
public boolean equals(Object object) {
if (!(object instanceof TestRun)) {
return false;
}
TestRun other = (TestRun) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "TestRun[ id=" + id + " ]";
}
}

并且:

  @Entity
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@Basic(optional=false)
@Column(nullable=false)
private String name;

@OneToMany(mappedBy="performedTest", cascade={CascadeType.MERGE, CascadeType.PERSIST})
private Collection<TestRun> appearsOnTestRuns;

public Collection<TestRun> getAppearsOnTestRuns() {
return appearsOnTestRuns;
}

public void setAppearsOnTestRuns(Collection<TestRun> appearsOnTestRuns) {
this.appearsOnTestRuns = appearsOnTestRuns;
}
//id based equals and hashcode
...
}

这种关系意味着我有一组执行了多次的测试,每次都与一个测试运行相关联。要创建 TestRun,我使用以下方法:

public void createTestRun(String name){
Test testPerformed = ejb.findByName(name); //Returns null iff forTest is not in the DB--> INSERT new Test
if (testPerformed == null){
testPerformed = EntityFactory.newTest(name);//I set the name for test
}
TestRun run = EntityFactory.newTestRun(testPerformed);
ejb.persist(run);
}

public class EntityFactory{
public static TestRun newTestRun(Test test){
TestRun run = new TestRun();
run.setPerformedTest(test);
return run;
}
public static Test newTest(String name){
Test test = new Test();
test.setName(name);
return test;
}
}

当 createTestRun 处理一个新的 Test(插入)时,Test 对象和 TestRun 一样被正确地持久化。但是当测试已经存在时,JPA(在我的例子中是 EclipseLink)无论如何都会尝试执行 INSERT:

....
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL110705102925930' defined on 'TEST'.
Error Code: -1
Call: INSERT INTO TEST (ID, NAME) VALUES (?, ?)

幕后发生了什么?问题是否与 Test 的 appearsOnTestRuns 属性有关?为什么 JPA 不理解 Test 已经存在于 DB 中(毕竟 id 属性是在 find 操作期间设置的,equals() 使用此值来决定 2 个 Tests 是否相等..)非常感谢你的帮助! :)

PS:您是否知道对这些概念进行了广泛解释的好教程/书籍?

最佳答案

首先,您应该检查整个 createTestRun 方法(它找到测试,在必要时创建它,然后创建 TestRun 实例并保存它)在单个事务中运行。

并且您的 newTestRun 方法应该初始化关系的两侧,这是双向的。开发人员有责任维护实体图的连贯性。它应该这样做:

public static TestRun newTestRun(Test test){
TestRun run = new TestRun();
run.setPerformedTest(test);
test.getAppearsOnTestRuns().add(run);
return run;
}

关于更新实体时出现 java.sql.SQLIntegrityConstraintViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6582150/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com