【问题标题】:Error setting database config property for IDatabaseConnection (HSQLDB)为 IDatabaseConnection (HSQLDB) 设置数据库配置属性时出错
【发布时间】:2017-05-19 04:41:35
【问题描述】:

我在下面包含了完全可测试的代码,当提供包含空字段的数据集xml 时会生成以下错误。下面还有一个示例dataset.xml

java.lang.IllegalArgumentException: table.column=places.CITY 值为 为空但必须包含一个值(要禁用此功能检查,请设置 DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS 为真)

线程here 相似但不同,因为它使用多个dbTester.getConnection() 而我的代码只使用一个,但有相同的错误。主要问题与这条线有关databaseConfig.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, Boolean.TRUE);
它似乎完全被忽略了。我尝试将init 代码放入@Test 方法中,但错误仍然存​​在。

dataset.xml

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <places address="123 Up Street" city="Chicago" id="001"/>
  <places address="456 Down Street" city="" id="002"/>
  <places address="789 Right Street" city="Boston" id="003"/>
</dataset>

代码:

import org.dbunit.IDatabaseTester;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DBConnectionIT {
    IDatabaseTester databaseTester = null;
    IDatabaseConnection iConn = null;
    Connection connection = null;

    @Before
    public void init() throws Exception {
        databaseTester = new JdbcDatabaseTester(org.hsqldb.jdbcDriver.class.getName(), "jdbc:hsqldb:mem:testdb;sql.syntax_pgs=true", "sa", "");
        iConn = databaseTester.getConnection();
        DatabaseConfig databaseConfig = iConn.getConfig();
        databaseConfig.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, Boolean.TRUE);
        connection = iConn.getConnection();
        createTable(connection);
        IDataSet dataSet = new FlatXmlDataSetBuilder().build(new File("dataset.xml"));
        databaseTester.setDataSet(dataSet);
        databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);
        databaseTester.setTearDownOperation(DatabaseOperation.DELETE_ALL);
        databaseTester.onSetup();
    }

    @Test
    public void testDBUnit() {
        try {
            PreparedStatement pst = connection.prepareStatement("select * from places");
            ResultSet rs = pst.executeQuery();
            while (rs.next()) {
                System.out.println(rs.getString(1));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void createTable(Connection conn) throws Exception {
        PreparedStatement pp = conn.prepareStatement(
                "CREATE TABLE PLACES" +
                        "(address VARCHAR(255), " +
                        "city TEXT, " +
                        "id VARCHAR(255) NOT NULL primary key)");
        pp.executeUpdate();
        pp.close();
    }
}

编辑(基于 César Rodríguez 的回答):

我现在在父类中重构了这个方法:

 protected void setUpDatabaseConfig(DatabaseConfig databaseConfig) {
        databaseConfig.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, Boolean.TRUE);
    }

并创建了一个子类@Overrides这个方法,但它说这个子类没有被使用。如何在父类中解决这个类(DBConnectionOverride),以解决我的问题?

class DBConnectionOverride extends DBConnectionIT {
    @Override
    protected void setUpDatabaseConfig(DatabaseConfig databaseConfig) {
        databaseConfig.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, true);
    }
}

【问题讨论】:

  • 仔细查看您链接到的问题。设置 FEATURE_ALLOW_EMPTY_FIELDS 属性后,您似乎需要使用 iConn 作为连接。似乎不需要调用 iConn.getConnection()。
  • @fredt,感谢您的反馈。我很困惑为什么你会说No call to iConn.getConnection() seems to be required,因为准备好的语句需要Connection而不是IDatabaseConnection。如果我只是在这些准备语句中传入IDatabaseConnection.getConnection(),它会返回相同的错误。您能否将您的建议落实到我提供的代码库中?我完全不知所措
  • 总是这行导致错误:databaseTester.onSetup();
  • @Nova 我不能用你的例子。我只是为你提供我的方式。

标签: postgresql unit-testing integration-testing hsqldb dbunit


【解决方案1】:

我偶然发现了正确的答案,至少可以解决我的问题。它一直与databaseTester.onSetup() 相关,可以简单地替换为DatabaseOperation.CLEAN_INSERT.execute(iConn, dataSet);。请随意评论为什么这似乎已经修复了错误。

【讨论】:

  • 你有没有再看这个?我可以在日志中看到 DbUnit 正在获取 iConn 并将配置设置为 FEATURE_ALLOW_EMPTY_FIELDS = true,但随后将其与其他几个功能一起初始化为 false。对我来说看起来像一个错误,但如果这对你有用,我的分析没有意义....
  • 我将错误追踪到DataSourceDatabaseTester,它在每个getConnection() 调用上实例化一个新的DatabaseConnection,但问题是——如果你调用DatabaseTester.onSetup(),它将被提供一个新的实例DatabaseConnection 在构造函数中为自己创建一个新的DatabaseConfig 实例,从而忽略您使用ALLOW_EMPTY_FIELDS 初始化的任何DatabaseConfig 实例。漏洞?不确定。显然从未以这种方式进行配置。在 DbUnit 的 Ant 相关代码中使用此配置的唯一位置。认为我必须访问 dbunit-user ML。
【解决方案2】:

您必须重写方法 setUpDatabaseConfig(DatabaseConfig config),如下所示:

@Override
protected void setUpDatabaseConfig(DatabaseConfig config) {
    config.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, true); 
}

希望对你有帮助

【讨论】:

  • 谢谢@César,但我不知道该把@Override 放在哪里。你能用我提供的代码告诉我最终代码应该是什么样子吗?我已将 databaseConfig.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, Boolean.TRUE); 行提取到您的代码建议的方法中,然后将您的 @Override 方法放入子类中,但它告诉我我的子类(我已命名为 DBConnectionOverride)没有在任何地方使用.我已经编辑了我的问题以显示这一点……出了什么问题?
  • 我认为您可以将覆盖方法放在您的 DBConnectionIT 类中。无论如何,如果你想创建一个像DBConnectionOverride 这样的新类,这个类不应该扩展DBConnectionIT 类。它是 DBConnectionIT 类扩展 DBConnectionOverride
  • 那不行,如果超类扩展了子类,那么@Override方法返回这个错误method does not override method from its superclass。如果子类extends 超类,则此错误消失,但是子类变灰(未使用)。如果您可以使用我在问题中提供的代码使其工作,然后在此处分享,我将奖励您 +1。
  • 我似乎完全不用Override就解决了我自己的问题。还是谢谢
【解决方案3】:

对我来说这是工作:

        IDatabaseConnection dbConn = new DatabaseDataSourceConnection(getDataSource());
        dbConn.getConfig().setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, true);
        DatabaseOperation.CLEAN_INSERT.execute(dbConn, getiDataSet(loadDBData.source()));

【讨论】:

  • 在我的上下文中使用 DatabaseOperation.CLEAN_INSERT.execute(iConn, dataSet); 时,我无法重现您的结果。您能否使用我提供的代码库提供解决方案?如果是这样,我会给你打勾。谢谢!
  • 总是这行导致错误:databaseTester.onSetup();
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 2017-01-02
  • 2020-07-07
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多