简单的场景以“违反完整性约束”结束
Posted
技术标签:
【中文标题】简单的场景以“违反完整性约束”结束【英文标题】:Simple scenario ends with "integrity constraint violation" 【发布时间】:2014-09-01 16:50:12 【问题描述】:我已经为此奋斗了好几个小时。我是 Hibernate 的新手,我想使用 Hibernate 4 和 HSQLDB(版本 2.3.2)做一些基本的映射。
这是我的代码:
TestTeam.java
package utils;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "TEST_TEAM")
public final class TestTeam
@Id
@Column(name = "NAME")
private String name;
@OneToMany(mappedBy = "name", fetch = FetchType.EAGER)
private List<TestPlayer> test1List;
public String getName()
return name;
public void setName(String name)
this.name = name;
public List<TestPlayer> getTest1List()
return test1List;
public void setTest1List(List<TestPlayer> test1List)
this.test1List = test1List;
public TestTeam()
public TestTeam(final String name, final List<TestPlayer> test1List)
this.name = name;
this.test1List = new ArrayList<>(test1List);
TestPlayer.java
package utils;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "TEST_PLAYER")
public class TestPlayer
@Id
@Column(name = "NAME")
private String name;
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "TEST_NAME", nullable = false)
private TestTeam test;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "PREVIOUS_TEST_TEAM")
private Map<Integer, TestTeam> previousTests;
public TestPlayer()
public String getName()
return name;
public void setName(String name)
this.name = name;
public TestTeam getTest()
return test;
public void setTestTeam(TestTeam test)
this.test = test;
public Map<Integer, TestTeam> getPreviousTests()
return previousTests;
public void setPreviousTests(Map<Integer, TestTeam> previousTests)
this.previousTests = previousTests;
public TestPlayer(final String name, final TestTeam test,
final Map<Integer, TestTeam> previousTests)
this.name = name;
this.test = test;
this.previousTests = new HashMap<>(previousTests);
以及应该运行它并很好地持久化实例的代码。
TestHibernate.java
package utils;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.SchemaExport;
public class TestHibernate
private static final SessionFactory SESSION_FACTORY;
static
final Properties properties = new Properties();
properties.setProperty("hibernate.connection.driver_class",
"org.hsqldb.jdbcDriver");
properties.setProperty("hibernate.connection.url",
"jdbc:hsqldb:hsql://localhost/xdb");
properties.setProperty("hibernate.connection.username", "SA");
properties.setProperty("hibernate.connection.password", "");
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.format_sql", "true");
properties.setProperty("hibernate.hbm2ddl.auto", "create");
properties.setProperty("hibernate.dialect",
"org.hibernate.dialect.HSQLDialect");
final Configuration configuration = new Configuration();
configuration.setProperties(properties).addPackage("utils")
.addAnnotatedClass(TestTeam.class)
.addAnnotatedClass(TestPlayer.class);
final ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
SESSION_FACTORY = configuration.buildSessionFactory(serviceRegistry);
final SchemaExport schemaExport = new SchemaExport(configuration);
schemaExport.setOutputFile("schema.sql");
schemaExport.create(true, false);
public static void main(String[] args)
try
final TestTeam previousTestTeam = new TestTeam();
previousTestTeam.setName("previousTest");
final TestTeam testTeam = new TestTeam();
testTeam.setName("Test");
final TestPlayer testPlayer1 = new TestPlayer();
testPlayer1.setName("Test1");
testPlayer1.setTestTeam(testTeam);
final Map<Integer, TestTeam> previousTestMap = new HashMap<>();
previousTestMap.put(1, previousTestTeam);
testPlayer1.setPreviousTests(previousTestMap);
final TestPlayer testPlayer2 = new TestPlayer();
testPlayer2.setName("Test2");
testPlayer2.setTestTeam(testTeam);
List<TestPlayer> test1List = Arrays
.asList(testPlayer1, testPlayer2);
testTeam.setTest1List(test1List);
final Session session = SESSION_FACTORY.openSession();
session.beginTransaction();
session.saveOrUpdate(previousTestTeam);
session.saveOrUpdate(testTeam);
session.saveOrUpdate(testPlayer1);
session.getTransaction().commit();
session.close();
finally
SESSION_FACTORY.close();
不幸的是,我收到以下异常,坦率地说我真的不知道为什么,父 (testTeam
) 的实例已经被保存,不是吗?
java.sql.SQLIntegrityConstraintViolationException:完整性约束违规:外键无父; FK_NMC24E737IXMNI0G869QRBOUI 表:TEST_PLAYER
我在这里做错了什么?
编辑
这其实很奇怪。如果我将 TestPlayer
类的 @Id
定义为 long 类型的字段,那么一切似乎都可以正常工作。
@Id
private long playerId;
后来改了一对多的注解是这样的
@OneToMany(mappedBy = "playerId")
这个星座不会产生任何异常。问题是,为什么我不能使用String
类型作为标识符???
【问题讨论】:
【参考方案1】:我面前没有环境,但我认为问题是你试图坚持testTeam
,而没有先坚持testPlayer1
(或testPlayer2
) .在您的@OneToMany
注释中,您没有指定cascade = Cascade.PERSIST
,这意味着这些玩家不会通过保存到testTeam
自动持久化。
【讨论】:
感谢您的回答。更改为Cascade.PERSIST
可以消除异常,但是TestPlayer
的数据根本不会在数据库中结束,只有TestTeam
的条目。
我更新了问题。看起来不能将Id
s 定义为String
s。以上是关于简单的场景以“违反完整性约束”结束的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 6:违反完整性约束:1452无法添加或更新子行:外键约束失败