2010年1月23日土曜日

iBATIS/nested set model

iBATIS で nested set をやってみる。 以下のようなサンプルデータで、とりあえず先祖だけ求めてみる。
mysql> select * from category;
+-------------+-------------+------+------+
| category_id | name        | lft  | rgt  |
+-------------+-------------+------+------+
|           1 | ELECTRONICS |    1 |   10 |
|           2 | TELEVISIONS |    2 |    9 |
|           3 | TUBE        |    3 |    4 |
|           4 | LCD         |    5 |    6 |
|           5 | PLASMA      |    7 |    8 |
+-------------+-------------+------+------+
図式化すると下図のようになる。
ELECTRONICS (1)110
 └TELEVISIONS (2)29
   ├ TUBE (3)34
   ├ LCD (4)56
   └ PLASMA (5)78
以下のようなコードで、LCD (4) を起点にして先祖を求めると、ELECTRONICS、TELEVISIONS が得られる事を確かめてみたい。
Category lcd = dao.getCategoryById(4);
List<Category> ascendants = dao.selectAscendants(lcd);
Category はこんな風なもの。lft、rgt はドメインモデルとは無関係なテクニカルな列なので、エンティティには含めない。
public class Category {
   private int id;
   private String name;
// getter/setter 略
}
で、DAO のselectAscendants()をこんな風に実装して、
@Override
public List<Category> selectAscendants(Category node) {
   return (List<Category>) getSqlMapClientTemplate()
     .queryForList("selectAscendants", node);
}
SQLMap の selectAscendants をこう書けば
<select id = "selectAscendants" 
          parameterClass="studies.spring.ibatis.Category"
          resultMap="result">
  SELECT parent.category_id, parent.name
  FROM category AS node, category AS parent
  WHERE parent.lft &lt; node.lft AND node.lft &lt; parent.rgt
          AND node.category_id = #id# 
  ORDER BY parent.lft
</select>
一発で祖先ノードが得られる。 なかなか iBATIS はシンプルで良いかも。 後は、Nested Set Model の追加時の操作をなんとかしたい。

0 件のコメント:

コメントを投稿