帳モメのotanuft

Stay hungry, stay foolish.

iBATIS 複雑なプロパティ(列挙型)

エンティティに複雑なプロパティを使用する場合。

例えば、列挙型。

テーブルにマッピングされる、データが列挙型である場合の

iBATISの定義の仕方。

まあ、列挙型でなくても、Hnadlerを登録すれば、ほぼ自由なことができる。

今回は、iBATIS Wikiにある例をチョット変更してみた。

How do I use a Custom Type Handler with complex property (Type Safe Enumeration)

Reportというテーブルをマッピングする。

このテーブルは、frequencyというType Safe Enumerationなプロパティを含む。

テーブル定義:

CREATE TABLE REPORT (

ID VARCHAR(5),

NAME VARCHAR(25),

DESCRIPTION VARCHAR(1000),

FREQUENCY NUMERIC(1)

)

Reportエンティティを作成する

package ibatis.domain;

import ibatis.domain.enum.FrequencyEnum;

public class Report {

String id;

String name;

String description;

FrequencyEnum frequency;

public final String getDescription() {

return description;

}

public final FrequencyEnum getFrequency() {

return frequency;

}

public final String getId() {

return id;

}

public final String getName() {

return name;

}

public final void setDescription(String description) {

this.description = description;

}

public final void setFrequency(FrequencyEnum frequency) {

this.frequency = frequency;

}

public final void setId(String id) {

this.id = id;

}

public final void setName(String name) {

this.name = name;

}

}

FrequencyEnumという列挙型を作る

Wikiのサンプルと違うところは、Commons LangのValuedEnumを使っているところ。

package ibatis.domain.enum;

import org.apache.commons.lang.enum.Enum;

import org.apache.commons.lang.enum.ValuedEnum;

public class FrequencyEnum extends ValuedEnum {

/**

* @param name

* @param value

*/

private FrequencyEnum(String name, int value) {

super(name, value);

}

private static final int FC_DAILY = 1;

private static final int FC_WEEKLY = 2;

private static final int FC_MONTHLY = 3;

private static final int FC_QUARTERLY = 4;

private static final String FN_DAILY = "Daily";

private static final String FN_WEEKLY = "Weekly";

private static final String FN_MONTHLY = "Monthly";

private static final String FN_QUARTERLY = "Quarterly";

public static final FrequencyEnum NULL =

new FrequencyEnum(null, 99999);

public static final FrequencyEnum DAILY =

new FrequencyEnum(FN_DAILY, FC_DAILY);

public static final FrequencyEnum WEEKLY =

new FrequencyEnum(FN_WEEKLY, FC_WEEKLY);

public static final FrequencyEnum MONTHLY =

new FrequencyEnum(FN_MONTHLY, FC_MONTHLY);

public static final FrequencyEnum QUARTERLY =

new FrequencyEnum(FN_QUARTERLY, FC_QUARTERLY);

public static Enum getEnum(int value) {

return (FrequencyEnum)getEnum(FrequencyEnum.class, value);

}

}

FrequencyEnumのハンドラーを作る

package ibatis.domain.enum;

import com.ibatis.sqlmap.client.extensions.ParameterSetter;

import com.ibatis.sqlmap.client.extensions.ResultGetter;

import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;

import java.sql.SQLException;

import java.sql.Types;

public class FrequencyEnumHandler implements TypeHandlerCallback {

/* PreparedStatementにデータをバインドするときに使われる */

public void setParameter(ParameterSetter setter, Object parameter)

throws SQLException {

if(parameter == null){

setter.setNull(Types.INTEGER);

} else {

FrequencyEnum frequency = (FrequencyEnum)parameter;

setter.setInt(frequency.getValue());

}

}

/* ResultSetから取り出すときに使われる */

public Object getResult(ResultGetter getter) throws SQLException {

int value = getter.getInt();

if(getter.wasNull()){

/* 値がNullの場合や、想定外の値の場合Nullに

なってしまうのが嫌ですが・・・ */

return null;

}

return FrequencyEnum.getEnum(value);

}

/* nullValueで指定した物を、置き換えるときに使われる(StringからのCast用) */

public Object valueOf(String s) {

return s;

}

}

SqlMapConfigにハンドラーを登録する

<sqlMapConfig>

<typeHandler javaType="ibatis.domain.enum.FrequencyEnum"

callback="ibatis.domain.enum.FrequencyEnumHandler"/>

</sqlMapConfig>

<properties/>, <settings/>, <typeAlias/>,

<typeHandler/>, <transactionManager/>, <sqlMap/>

の順番で書かないとエラーになるので注意。