简单的场景以“违反完整性约束”结束

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 的条目。 我更新了问题。看起来不能将Ids 定义为Strings。

以上是关于简单的场景以“违反完整性约束”结束的主要内容,如果未能解决你的问题,请参考以下文章

SQLSTATE [23000]:违反完整性约束:1217

违反完整性约束:1048 列“school_id”不能为空

Laravel 6:违反完整性约束:1452无法添加或更新子行:外键约束失败

Laravel 删除(违反完整性约束)

SQLSTATE [23000]:违反完整性约束:4025 CONSTRAINT

Laravel 迁移 - 违反完整性约束:1452 无法添加或更新子行:外键约束失败