Bean間のデータコピーについて

責務の切り分け等を理由に、「ActionForm」「DTO」「Entity」間でデータをコピーすることは多い。
要素毎にコピーを記述することも出来るが、要素の数が多くなると、記述ミス等でバグを生む原因にもなる。

この様な場合は、「org.seasar.framework.beans.util.Beans」の「copy」メソッドを使用すると便利である。
Beans#copyは、同名の要素間のデータコピーを一括で行ってくれる。
(入れ子の要素や、List要素内のデータまでコピーされる。)

<使用方法>

Beans.copy(<コピー元Bean>, <コピー先Bean>).execute();

<使用例>
[前提]
下記の「SampleDto」から「IndexForm」にデータをコピーする場合を例とする。

package jp.co.smp.beancopy.dto;

import java.sql.Date;
import java.util.List;

public class SampleDto {

	public String id;
	public String userName;
	public int year;
	public Date updateDate;
	public SampleItemDto mainItem;
	public List<SampleItemDto> itemList;
}
package jp.co.smp.beancopy.form;

import java.util.List;
import jp.co.smp.beancopy.dto.SampleItemDto;

public class IndexForm {

	public String id;
	public String userName;
	public int year;
	public String updateDate;
	public SampleItemDto mainItem;
	public List<SampleItemDto> itemList;
}

要素として使用しているSampleItemDto

package jp.co.smp.beancopy.dto;

public class SampleItemDto {

	public String code;
	public String itemName;
	public int price;
	public int num;
}

[コピー実施]

package jp.co.smp.beancopy.action;

import javax.annotation.Resource;
import jp.co.smp.beancopy.dto.SampleDto;
import jp.co.smp.beancopy.form.IndexForm;
import jp.co.smp.beancopy.service.SampleService;
import net.arnx.jsonic.JSON;
import org.seasar.framework.beans.util.Beans;
import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;

public class IndexAction {

	@Resource
	protected SampleService sampleService;

	@ActionForm
	@Resource
	protected IndexForm indexForm;

	@Execute(validator = false)
	public String index() {
		
		//SampleDtoにダミーデータを詰め込む
		SampleDto dto = sampleService.doLogic();

		//コピーの実施
		Beans.copy(dto, indexForm).execute();

		//確認のためにコピー先をコンソールに出力する※
		System.out.println(JSON.encode(indexForm, true));

		return "index.jsp";
	}
}


出力には、「JSONIC」ライブラリを使用している。
使用するには、ビルドパスにライブラリとして登録する必要がある。
JSONIC公式サイト

ダミーデータを作成するSampleService

package jp.co.smp.beancopy.service;

import java.sql.Date;
import java.util.ArrayList;
import jp.co.smp.beancopy.dto.SampleDto;
import jp.co.smp.beancopy.dto.SampleItemDto;

public class SampleService {

	public SampleDto doLogic() {

		SampleDto dto = new SampleDto();

		dto.id = "0001";
		dto.userName = "sampleUser";
		dto.year = 25;
		dto.updateDate = new Date(System.currentTimeMillis());

		dto.mainItem = new SampleItemDto();
		dto.mainItem.code = "i-d-main-001";
		dto.mainItem.itemName = "item_name_main";
		dto.mainItem.price = 30;
		dto.mainItem.num = 100;

		dto.itemList = new ArrayList<SampleItemDto>();

		for (int i = 0; i < 10; i++) {

			SampleItemDto itemDto = new SampleItemDto();

			itemDto.code = "i-d-00" + i;
			itemDto.itemName = "item_name_" + i;
			itemDto.price = 30 * (i + 1);
			itemDto.num = i + 1;

			dto.itemList.add(itemDto);
		}

		return dto;
	}
}

<実行結果>
コンソールに下記の内容が出力され、コピーが行われたことを確認することができる

{
	"id": "0001",
	"itemList": [
		{
			"code": "i-d-000",
			"itemName": "item_name_0",
			"num": 1,
			"price": 30
		},
		{
			"code": "i-d-001",
			"itemName": "item_name_1",
			"num": 2,
			"price": 60
		},
		{
			"code": "i-d-002",
			"itemName": "item_name_2",
			"num": 3,
			"price": 90
		},
		{
			"code": "i-d-003",
			"itemName": "item_name_3",
			"num": 4,
			"price": 120
		},
		{
			"code": "i-d-004",
			"itemName": "item_name_4",
			"num": 5,
			"price": 150
		},
		{
			"code": "i-d-005",
			"itemName": "item_name_5",
			"num": 6,
			"price": 180
		},
		{
			"code": "i-d-006",
			"itemName": "item_name_6",
			"num": 7,
			"price": 210
		},
		{
			"code": "i-d-007",
			"itemName": "item_name_7",
			"num": 8,
			"price": 240
		},
		{
			"code": "i-d-008",
			"itemName": "item_name_8",
			"num": 9,
			"price": 270
		},
		{
			"code": "i-d-009",
			"itemName": "item_name_9",
			"num": 10,
			"price": 300
		}
	],
	"mainItem": {
		"code": "i-d-main-001",
		"itemName": "item_name_main",
		"num": 100,
		"price": 30
	},
	"updateDate": "2013/09/02",
	"userName": "sampleUser",
	"year": 25
}

<お勧め書籍>