Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

DbUnitで読み込むファイルの値にnullを設定する

DbUnitでは初期値や期待値をXMLやExcelに記述することができる。
ただ、nullを表現したいときは困ってしまう。
たとえばXMLで次のように記述したとする。

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <HUMAN NAME="jyukutyo" NULLCOLUMN="" />
</dataset>

この場合、NULLCOLUMNはnullではなく空文字となる。
本当にそうなるかサンプルプログラムで読み込んで出力してみる。

	public static void main(String[] args) throws Exception {

		FlatXmlDataSet dataSet = new FlatXmlDataSet(new File("data.xml"));
		output(dataSet);

	}

	protected static void output(IDataSet dataSet) throws DataSetException {
		for (String name : dataSet.getTableNames()) {
			ITable table = dataSet.getTable(name);
			System.out.println("Table name:"
				+ table.getTableMetaData().getTableName());
			Column[] columns = table.getTableMetaData().getColumns();
			for (int i = 0; i < table.getRowCount(); i++) {
				System.out.print("Row:" + i + "[");
				for (int j = 0; j < columns.length; j++) {
					Column column = columns[j];
					System.out.print(column.getColumnName() + "={"
						+ table.getValue(i, column.getColumnName()) + "},");
				}
				System.out.println("]");
			}
		}
	}

さっきのXMLをdata.xmlとしてる。
実行するとこう出力される。

Table name:HUMAN
Row:0[NAME={jyukutyo},NULLCOLUMN={},]

もし、nullであればこう出力されなければならない*1

Table name:HUMAN
Row:0[NAME={jyukutyo},NULLCOLUMN={null},]

Excelを使っていても同様の事態になる。


ではDbUnitはnullを初期値や期待値として表現できないのか、
というとそうではなくて、ReplacementDataSetクラスを利用する。
これはDataSetをラップするオブジェクトで、後から値を置き換えることができる。


なので、XMLをこう変更する。

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<HUMAN NAME="jyukutyo" NULLCOLUMN="[null]" />
</dataset>

[null]と書いたがこれは任意でよく、後から置き換えるためのマーカーにすぎない。
プログラムで[null]をnullに置き換えるよう変更する。

	public static void main(String[] args) throws Exception {

		FlatXmlDataSet dataSet = new FlatXmlDataSet(new File("data.xml"));
		
		ReplacementDataSet replacementDataSet = new ReplacementDataSet(dataSet);
		replacementDataSet.addReplacementObject("[null]", null);
		
		output(replacementDataSet);

	}

実行するとNULLCOLUMNはnullになる。

Table name:HUMAN
Row:0[NAME={jyukutyo},NULLCOLUMN={null},]

これを応用すれば、たとえばTimestampで現在時刻を設定するということもできる。

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
	<HUMAN NAME="jyukutyo" NULLCOLUMN="[null]" TIMESTAMP="[now]" />
</dataset>
replacementDataSet.addReplacementObject("[now]", new Timestamp(System.currentTimeMillis()));
Table name:HUMAN
Row:0[NAME={jyukutyo},NULLCOLUMN={null},TIMESTAMP={2008-08-21 13:52:22.044},]

ちなみに、置き換える値が複数の行にあっても、すべて置換される。

*1:+演算子はStringBuffer#append()だから