DbUnit 无法清理插入:外键约束

Posted

技术标签:

【中文标题】DbUnit 无法清理插入:外键约束【英文标题】:DbUnit fails to clean-insert: foreign key constraint 【发布时间】:2014-11-24 22:19:50 【问题描述】:

我正在询问并回答这个问题以供将来参考,因为我认为我找到了解决 DbUnit 常见问题的体面解决方案。我希望它对某人有所帮助。

我正在使用DbUnit 2.5.0TestNG 6.8.8。我的用例是包含 3 个实体的数据库的一部分。有一个 ServiceUser 持有一个外键,指向 AdministrableUserGroup

我遵循http://city81.blogspot.com/2011/03/testing-jpa-entities-using-dbunit.html的大部分代码示例

public abstract class AbstractDatabaseTest 
    protected EntityManager em; // initialized elsewhere
    private IDatabaseConnection connection;
    private IDataSet dataset;

    @BeforeClass
    private void setupDatabaseResource() throws Exception 
        // using Hibernate
        connection = new DatabaseConnection(((SessionImpl) (em.getDelegate())).connection());
        connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new HsqldbDataTypeFactory());

        // full database export
        IDataSet fullDataSet = connection.createDataSet();

        final String datasetPath = String.format("%s%s", RESOURCE_FOLDER, "Testing.xml");
        FlatXmlDataSet.write(fullDataSet, new FileOutputStream(datasetPath));

        FlatXmlDataSetBuilder flatXmlDataSetBuilder = new FlatXmlDataSetBuilder();
        flatXmlDataSetBuilder.setColumnSensing(true);
        dataset = flatXmlDataSetBuilder.build(new FileInputStream(datasetPath));
    

    @AfterMethod
    public void cleanDB() throws Exception 
        em.getTransaction().begin();
        DatabaseOperation.CLEAN_INSERT.execute(connection, dataset);
        em.getTransaction().commit();
    

这样的结果如下XMLDataSet(数据省略):

<dataset>
  <administrable/>
  <serviceuser/>
  <usergroup/>
</dataset>

TestNG 执行@AfterMethod 时,我得到以下异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException
Cannot delete or update a parent row: a foreign key constraint fails (`testing_db`.`serviceuser`, CONSTRAINT `FK_gyylcfbhpl2ukqs5rm7sq0uy8` FOREIGN KEY (`userGroup_id`) REFERENCES `usergroup` (`id`))

【问题讨论】:

【参考方案1】:

问题是我上面创建的XMLDataSet不知道表中的外键约束,按字母顺序创建表列表。然而,CLEAN_INSERT 操作获取表列表并以相反的顺序遍历它,它要求在引用的实体(这里:UserGroup)之前删除外键引用(这里:ServiceUser.userGroup_id)。

我通过Unitils doesn't work和http://forum.spring.io/forum/spring-projects/data/12868-dbunit-test-fails-mysql-server-hates-me?p=337672#post337672找到了这些信息

对 DbUnit 文档的一些小的挖掘导致了创建数据集的更正方法,该方法检查外键依赖关系并尝试对实体进行适当的排序:

IDataSet fullDataSet = new FilteredDataSet(new DatabaseSequenceFilter(connection), connection.createDataSet());

结果:

<dataset>
  <administrable/>
  <usergroup/>
  <serviceuser/>
</dataset>

这将正确地CLEAN_INSERT

免责声明:我没有遇到循环依赖或自引用外键,也没有测试过这个修复可以处理它们。

【讨论】:

我不确定你在问什么。关于代码 sn-p 我什么都不说,所有相关代码都可以在问题或答案中找到。 您使用的代码 IDataSet sn-p。你把它放在什么文件里了? @BeforeClass方法中替换IDataSet fullDataSet = connection.createDataSet(); “但是,CLEAN_INSERT 操作获取表列表并以相反的顺序遍历它”

以上是关于DbUnit 无法清理插入:外键约束的主要内容,如果未能解决你的问题,请参考以下文章

在 PHPUnit/DBUnit 中设置外键约束

转:使用DBUnit测试时违反外键约束的解决办法

无法将值插入表中,外键约束不断失败

如何修复“无法添加或更新子行:外键约束失败”[重复]

MySQL导入数据库--开启/关闭外键约束

sql。两个间的外键约束和插入数据问题