Ibatis TypeHandler使用總結ibatis中有一個TypeHandler(準確的說應該是TypeHandlerCallback), 這個介面一般用的比較少, google一下, 大部分就是用來將資料庫中的值與java的枚舉值或者clob與字串之間的轉換. 最近本人也用到了這個東東. 不過我們使用的是將儲存在資料庫中以一定分隔字元串連的字串轉換成List類型. 開始不知道有TypeHandler這個東東, 於是在JavaBean中定義了兩個屬性, 一個string類型的, 一個List類型的,
然後內部之間轉換, 這種做法有一個弊端, 就是實際上在對一個屬性操作的時候, 會有兩個介面, 一方面給使用方造成了困惑, 另一個維護起來也不方便, 於是將轉換過程完全封裝, 對外提供提一個提供者, 成了一個必要的選擇.
先來看看TypeHandlerCallback的定義: Java代碼
- public interface TypeHandlerCallback {
- public void setParameter(ParameterSetter setter, Object parameter)
- throws SQLException;
-
- public Object getResult(ResultGetter getter)
- throws SQLException;
-
- public Object valueOf(String s);
public interface TypeHandlerCallback { public void setParameter(ParameterSetter setter, Object parameter) throws SQLException; public Object getResult(ResultGetter getter) throws SQLException; public Object valueOf(String s);
代碼很好理解, 而且為了說明如何使用, 作者不惜在注視中給出了一個example.
代碼很好理解, setParameter()方法主要是給PrepareStatement賦值. 因此是在insert, update, delete這些操作的時候, 指定傳遞參數用的.
getResult()方法用來將ResultSet結果集中的內容轉換到JavaBean中對應的屬性.
valueOf()主要是用來當沒有指定的值的時候, 指定預設值的. 主要是ResultSet到JavaBean之間的轉換的時候會用到. 最好不要返回null值, 它跟nullValue相關.
下面是一個將資料庫中";"分隔的字串與DO中的list對象之間的轉換的實現: Java代碼
- public class PropertiesTypeHandlerCallback implements TypeHandlerCallback {
- private static final String LIST_SPLIT_FLAG = ";";
-
- public Object getResult(ResultGetter getter) throws SQLException {
- String properties = getter.getString();
- return CollectionUtils.stringToList(properties, LIST_SPLIT_FLAG, new
- StringConvertor<Property>() {
- public Property convert(String str) {
- return Property.valueOf(str);
- }
- });
- }
-
- @SuppressWarnings("unchecked")
- public void setParameter(ParameterSetter setter, Object parameter) throws SQLException {
- List<String> propertyList = (List<String>) parameter;
- setter.setString(CollectionUtils.listToString(propertyList, LIST_SPLIT_FLAG));
- }
-
- public Object valueOf(String s) {
- return Collections.EMPTY_LIST;
- }
- }
public class PropertiesTypeHandlerCallback implements TypeHandlerCallback { private static final String LIST_SPLIT_FLAG = ";"; public Object getResult(ResultGetter getter) throws SQLException { String properties = getter.getString(); return CollectionUtils.stringToList(properties, LIST_SPLIT_FLAG, new StringConvertor<Property>() { public Property convert(String str) { return Property.valueOf(str); } }); } @SuppressWarnings("unchecked") public void setParameter(ParameterSetter setter, Object parameter) throws SQLException { List<String> propertyList = (List<String>) parameter; setter.setString(CollectionUtils.listToString(propertyList, LIST_SPLIT_FLAG)); } public Object valueOf(String s) { return Collections.EMPTY_LIST; }}
接下來是sqlmap的對應檔中進行配置.
針對sql返回結果的轉換, 需要在對應的resultMap中指定一下, 比如這樣寫: Xml代碼
- <result property="propertyList" column="PROPERTIES" typeHandler="com.mysoft.dao.ibatis.support.PropertiesTypeHandlerCallback"/>
<result property="propertyList" column="PROPERTIES" typeHandler="com.mysoft.dao.ibatis.support.PropertiesTypeHandlerCallback"/>
針對賦值的參數的設定, 有兩種做法, 一種是在parameterMap中的parameter標籤中的設定typeHandler屬性為對應的callback, 這種做法有一種不好的地方, 就是不同的賦值map, 需要單獨定義, 這個反而增加了工作量. 而且使用parameterMap之後, sql語句中的原來在##中指定賦值名稱需要改成?, 賦值遵循parameterMap中的定義順序, 這種做法既繁瑣, 可維護性也不好, 因此推薦採用inlineParameter的做法, 比如這樣寫:
Sql代碼
- #propertyList,handler=com.taobao.item.dao.ibatis.support.ItemVerticalPropertiesTypeHandlerCallback#
#propertyList,handler=com.taobao.item.dao.ibatis.support.ItemVerticalPropertiesTypeHandlerCallback#
對於TypeHandler的配置, 還有一種做法, 就是在sqlmap中對某一種類型, 使用typeHandler標籤進行定義, 比如這樣寫: Java代碼
- <typeHandler javaType="" callback=""/>
<typeHandler javaType="" callback=""/>
注意這個需要定義在sqlMapConfig標籤下.