【问题标题】:dbUnit support for Postgresql ArraydbUnit 对 Postgresql 数组的支持
【发布时间】:2016-03-27 16:36:08
【问题描述】:

我正在为数据库组件编写一些单元测试。为此,我使用了专用的测试数据库(Postgresql,与生产数据库相同)和 dbUnit。

现在我想为我的整个测试数据库创建一个 XML 转储。我目前使用FAQ page of dbUnit中的代码

IDatabaseConnection connection = new DatabaseConnection(conn);
connection.getConfig().setProperty("http://www.dbunit.org/properties/datatypeFactory", new PostgresqlDataTypeFactory());
IDataSet fullDataSet = connection.createDataSet();
FlatXmlDataSet.write(fullDataSet, new FileOutputStream("full.xml"));

这一切都很好,除了Array 类型的列。 dbUnit 只是将它们排除在外。我希望可以通过添加 PostgresqlDataTypeFactory 来修复它,但这并没有改变任何事情。

有人知道如何在 dbUnit 中添加对 postgresql 数组的支持吗?

【问题讨论】:

    标签: java arrays postgresql dbunit


    【解决方案1】:

    我在github上找到了这个项目:https://github.com/JarnTang/dbunit-ext

    我正在使用它的 ArrayDataType 类,稍作修改:

    import org.dbunit.dataset.ITable;
    import org.dbunit.dataset.datatype.AbstractDataType;
    import org.dbunit.dataset.datatype.TypeCastException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.util.StringUtils;
    
    import java.lang.invoke.MethodHandles;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    
    public class ArrayDataType extends AbstractDataType {
    
        private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
        private static final Class CLASS_TYPE = Array.class;
    
        public ArrayDataType(String name, int sqlType, boolean isNumber) {
            super(name, sqlType, CLASS_TYPE, isNumber);
        }
    
        @Override
        public Object typeCast(Object value) throws TypeCastException {
            if (value == null || value == ITable.NO_VALUE) {
                return null;
            }
    
            if (value instanceof String) {
                return new String[]{(String) value};
            }
            if (value instanceof String[]) {
                return value;
            }
    
            if (value instanceof Date ||
                    value instanceof Time ||
                    value instanceof Timestamp) {
                return new String[]{value.toString()};
            }
    
            if (value instanceof Boolean) {
                return new String[]{value.toString()};
            }
    
            if (value instanceof Number) {
                try {
                    return new String[]{value.toString()};
                } catch (NumberFormatException e) {
                    throw new TypeCastException(value, this, e);
                }
            }
    
            if (value instanceof Array) {
                try {
                    Array a = (Array) value;
                    return a.getArray();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            if (value instanceof Blob) {
                try {
                    Blob blob = (Blob) value;
                    byte[] blobValue = blob.getBytes(1, (int) blob.length());
                    return typeCast(blobValue);
                } catch (SQLException e) {
                    throw new TypeCastException(value, this, e);
                }
            }
    
            if (value instanceof Clob) {
                try {
                    Clob clobValue = (Clob) value;
                    int length = (int) clobValue.length();
                    if (length > 0) {
                        return clobValue.getSubString(1, length);
                    }
                    return "";
                } catch (SQLException e) {
                    throw new TypeCastException(value, this, e);
                }
            }
    
            log.warn("Unknown/unsupported object type '{}' - " +
                            "will invoke toString() as last fallback which " +
                            "might produce undesired results",
                    value.getClass().getName());
            return value.toString();
        }
    
        @Override
        public Object getSqlValue(int column, ResultSet resultSet)
                throws SQLException, TypeCastException {
            if (log.isDebugEnabled())
                log.debug("getSqlValue(column={}, resultSet={}) - start", column, resultSet);
    
            String value = resultSet.getString(column);
            if (value == null || resultSet.wasNull()) {
                return null;
            }
            return value;
        }
    
        @Override
        public void setSqlValue(Object value, int column, PreparedStatement statement)
                throws SQLException, TypeCastException {
            if (log.isDebugEnabled())
                log.debug("setSqlValue(value={}, column={}, statement={}) - start",
                        value, column, statement);
    
            Array array = isNumber() ? statement.getConnection().createArrayOf("integer", toArray(value)) :
                    statement.getConnection().createArrayOf("text", toArray(value));
    
            statement.setObject(column, array);
        }
    
    
        private Object[] toArray(Object value) {
            List list = new ArrayList(0);
            if (value instanceof String) {
                String valueStr = (String) value;
                if (!StringUtils.isEmpty(valueStr)) {
                    valueStr = valueStr.replaceAll("[{}]", "");
                    return valueStr.split(",");
                }
            }
            return list.toArray();
    
        }
    
    }
    

    那你需要扩展PostgresqlDataTypeFactory,例如:

    import org.dbunit.dataset.datatype.DataType;
    import org.dbunit.dataset.datatype.DataTypeException;
    import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
    
    public class CustomPostgresqlDataTypeFactory extends PostgresqlDataTypeFactory{
    
        @Override
        public DataType createDataType(int sqlType, String sqlTypeName, String tableName, String columnName) throws DataTypeException {
            if (sqlType == 2003) {
                if (sqlTypeName.equals("_text"))
                    return new ArrayDataType(sqlTypeName, sqlType, false);
                if (sqlTypeName.contains("int"))
                    return new ArrayDataType(sqlTypeName, sqlType, true);
    
                throw new UnsupportedSqlTypeException("Unsupported sql type: " + sqlTypeName);
            }
    
            return super.createDataType(sqlType, sqlTypeName, tableName, columnName);
        }
    }
    

    并将CustomPostgresqlDataTypeFactory 设置为IDatabaseConnection

    IDatabaseConnection conn = databaseTester.getConnection();
    conn.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY,
                    new CustomPostgresqlDataTypeFactory());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-23
      • 2020-11-24
      • 1970-01-01
      • 1970-01-01
      • 2019-12-30
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      相关资源
      最近更新 更多