リフレクションを使用した private field へのアクセス

 hibernate でバージョンによるオプティミスティックロックを行う場合、access="field" にすることがあります。しかし、access="field"にしてしまうと、テストケースを作成するのが難しくなります。例えば、User というクラスがあり、フィールドが以下のように定義され、version フィールドにはsetter が存在しないとします。

private Long version;
private Long id;
private String name;
private String password;

/**
 * @hibernate.version
 * 		type="long"
 * 		unsaved-value="-1
 * 		access="field"
 */
public final Long getVersion() {
	return this.version;
}
public final void setVersion(Long version) {
	this.version = version;
}

/**
 * @hibernate.id
 * generator-class="assigned"
 */
public final Long getId() {
	return this.id;
}
public final void setId(Long id) {
	this.id = id;
}
/**
 * @hibernate.property
 */
public final String getName() {
	return this.name;
}
public final void setName(String name) {
	this.name = name;
}
/**
 * @hibernate.property
 */
public final String getPassword() {
	return this.password;
}
public final void setPassword(String password) {
	this.password = password;
}

オプティミスティックテスト用のデータ作成に以下のようなオペレーションを行いたいところですが、上記の例では setVersion() メソッドが存在しないためにうまくいきません。

User user = new User();
user.setVersion();
user.setId();
user.setname();
user.setPassword();

version フィールドに対する setter を用意するという選択肢も考えられますが、業務アプリケーション開発者が、アーキテクチャの視点で用意されたメタ情報にアクセスできるのは好ましくありません。

そのような場合は、リフレクションを用いることにより、プライベートフィールドにアクセスします。

Field f = User.class.getDeclaredField("version");
f.setAccessible(true);
f.set(user, new Long(1));