注記を使用したORM


1.Nutzでの注記の適用
nutzでは、データベースに対応するpojoについて、fieldとtableのcolumn間の対応を注釈で構成したり、注釈で2つのpojo間の関係を構成したりすることができます.例えば、私はPOJOという名前の「Box」を持っています.2つのフィールドが含まれています.
(1)
@Column("boxid")
@Id
private int id;

フィールドidの場合、@Column("boxid")はcolumn"boxid"、@Idはデータベースに対応することを示し、これはプライマリ・キーです.
 
(2)
@Many(target = BoxInfo.class, field = "boxId")
private BoxInfo[] infos;

この注記は、BoxとBoxInfoの2つのPOJOの間に1対多の関係があることを宣言しています.Box------>複数のBoxInfo、つまり1つのboxidを指定すると、BoxInfoに対応するtableに複数のレコードを見つけることができ、「boxId」を通じて「Box」に関連付けることができます.この例をはっきり言わなかったらnutzプロジェクトのwikiを参考にして、もっと実用的な注釈と紹介を見つけることができます.
 
2.注釈の簡単な紹介
その前に注釈を使ったことがあると信じています.junit 4、hibernate 3などのフレームワークやツールを使ったことがあると思います.少なくとも@Overrideを使ったことがあります(これを使ったことがないとは信じません).
Annotationはjdk 1です.5導入され、その導入はsrc、classまたはruntimeレベルでプログラムの情報を増加させる新しい手段を与えた.プログラマーは自分でAnnotationを定義して自分のプログラムに使用することができます.もちろん、自分のAnnotationプロセッサを作成する必要があります.
 
3.簡単な例
(3.1)もし私が2つのAnnotation(@Table Name,@Column)を定義してPOJOに使用したい場合、@Table NameはPOJOのクラスに使用し、データベースに対応するどのtableに対応するかを宣言し、@ColumnはPOJOのfieldに使用し、対応するcolumnを示すために使用する場合、私はこのようにすることができます.
 
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName{
	String value();
}

@Target(ElementType.TYPE)は、「クラス、インタフェース(注釈タイプを含む)または列挙宣言」であることを説明し、JDKAPIを開き、「java.lang.annotation.ElementType」を探しに行くと、より多くのオプションのTargetが見つかります.
@Retention(RetentionPolicy.RUNTIME)は、「コンパイラはクラスファイルにコメントを記録し、実行時にVMはコメントを保持するので、反射的に読み取ることができる」ことを示しています.
もう1つ定義します
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {

	String value() default "";

}

 
(3.2)この2つの注釈を私のcodeに適用する
@TableName("tbl_user")
public class User {

	@Column
	private int id;

	@Column
	private String name;

	@Column("age")
	private int userAge;

	public int getId() {return id;}
	public void setId(int id) {this.id = id;}
	public String getName() {return name;}
	public void setName(String name) {this.name = name;}
	public int getUserAge() {return userAge;}
	public void setUserAge(int userAge) {this.userAge = userAge;}
}

(3.3)プロセッサを書き、この2つの注釈を用いたPOJOのためにInsert文を生成したい場合は、そうすることができます.(例を複雑にしないために、ここでは最も無邪気で幼稚な状況だけを考慮し、すべてのコードを1つにして、どういう意味かを理解すればいい).
 
 
public class SqlGetter {

	public static void main(String[] args) throws Exception {
		User user = new User();
		user.setId(1);
		user.setName("Tom");
		user.setUserAge(12);
		System.out.println(new SqlGetter().getInsertSql(user));		
	}

	public String getInsertSql(Object obj) throws Exception {
		//  table  
		String tableName=obj.getClass().getAnnotation(TableName.class).value();
		
		//   column---value
		HashMap<String, Object> kvs = new HashMap<String, Object>();
		Field[] fs = obj.getClass().getDeclaredFields();
		for (Field f : fs) {
			String cn = this.getFieldColumn(f);
			if (cn != null) {
				kvs.put(f.getName(), this.getFieldValue(obj,f));
			}
		}
		//  SQl
		StringBuilder prefix = new StringBuilder();
		StringBuilder suffix = new StringBuilder();
		for(Iterator<String> it=kvs.keySet().iterator();it.hasNext();){
			String key=it.next();
			prefix.append(key);
			suffix.append(kvs.get(key));
			if (it.hasNext()) {
				prefix.append(",");
				suffix.append(",");
			}
		}		
		return String.format("INSERT INTO %s (%s) VALUES (%s)", tableName,prefix,suffix);
	}

	private String getFieldColumn(Field field) {
		Column column = field.getAnnotation(Column.class);
		if (column != null) {
			if ("".equals(column.value()))
				return field.getName();
			else {
				return column.value();
			}
		}
		return null;
	}

	private Object getFieldValue(Object obj,Field field) throws Exception {
		String name = field.getName();
		String c = name.substring(0, 1);
		name = name.replaceFirst(c, c.toUpperCase());
		Method m = obj.getClass().getMethod("get" + name, new Class<?>[] {});
		return m.invoke(obj, new Object[] {});
	}

}

意外なことに、出力は「INSERT INTO tbl_user(id,name,userAge)VALuES(1,Tom,12)」であるはずです.この例では、多くの問題が見つかります.
(1)コード構造差(2)異常処理差(3)sql文にstringタイプに引用符が付けられていないため、結果は一致しません.(4).....
しかし、もしあなたが以前Annotationについて特に理解していなかったら、本文がレンガを投げて玉を引く役割を果たすことを望んでいます.
 
最後に、Nutzのdao機能を使って、Annotationが私たちに与えた便利さを体験することができます.http://code.google.com/p/nutz/