Atea - Hero's Grave

          面向對象,開源,框架,敏捷,云計算,NoSQL,商業智能,編程思想。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            40 隨筆 :: 0 文章 :: 28 評論 :: 0 Trackbacks
          s2dao是基于seasar2的orm框架,使用簡單且功能比較強大。官方網站為http://s2dao.seasar.org/,中英日文檔皆有。
          如果對hibernate望而生畏,而只是尋找一個替代jdbc的工具的話,s2dao算是一個不錯的選擇。某種程度上來講,s2dao可能會比較像ibatis(筆者沒有使用過ibatis)。

          具體編碼來說,基本上是一個interface(相當于DAO)對應一個javabean。這里的javabean不是pojo,不具備持久性,只是作為dao方法返回值的容器,所以可以很方便的實現復雜的多表檢索。
          interface的具體方法體不用自己手寫,通過系統的interceptor可自動填充并實現。

          下面對使用做具體介紹。本文使用的s2dao版本為1.0.49。
          DB中有三個表:


          1.單表

          Example.java為Example表的容器類(s2dao習慣稱之為DTO,雖然這個稱呼不是很恰當)
           1 package com.hg.s2dao.dto;
           2 
           3 import org.seasar.dao.annotation.tiger.Bean;
           4 
           5 @Bean(table = "EXAMPLE")
           6 public class Example {
           7 
           8     private String id;
           9     private String name;
          10 
          11     public String getId() {
          12         return id;
          13     }
          14 
          15     public void setId(String id) {
          16         this.id = id;
          17     }
          18 
          19     public String getName() {
          20         return name;
          21     }
          22 
          23     public void setName(String name) {
          24         this.name = name;
          25     }
          26 
          27     public String toString() {
          28         return "id: " + id + " name: " + name;
          29     }
          30 
          31 }
          使用@Bean注釋表明此DTO所對應的DB表名,剩下的就是字段和getter、setter了。
          ※注:當進行多表檢索時,@Bean指定其中的一個table即可。

          接下來是DAO,代碼大體比較易懂。
           1 package com.hg.s2dao.dao;
           2 
           3 import java.util.List;
           4 
           5 import org.seasar.dao.annotation.tiger.Arguments;
           6 import org.seasar.dao.annotation.tiger.Query;
           7 import org.seasar.dao.annotation.tiger.S2Dao;
           8 import org.seasar.dao.annotation.tiger.Sql;
           9 
          10 import com.hg.s2dao.dto.Example;
          11 
          12 @S2Dao(bean = Example.class)
          13 public interface ExampleDao {
          14 
          15     // C////////////////////////////////////
          16     /** insert multi */
          17     int insertExamples(java.util.List<Example> exps);
          18 
          19     /** insert single */
          20     int insertExample(Example exp);
          21 
          22     // R////////////////////////////////////
          23     /** search all */
          24     List<Example> findAll();
          25 
          26     /** sql command */
          27     @Sql("SELECT MAX(E.ID) FROM EXAMPLE E ")
          28     String findIDMax();
          29 
          30     /** contains condition */
          31     @Query("ID = ? AND NAME = ?")
          32     Example findAllByIdAndName(String id, String name);
          33 
          34     /** when multi use or self-define order */
          35     @Arguments( { "id1""id2" })
          36     @Query("ID = /*id2*/ OR ID = /*id1*/ ")
          37     List<Example> findAllById(String id1, String id2);
          38 
          39     /** list param */
          40     @Arguments( { "ids" })
          41     @Query("ID IN /*ids*/('') ")
          42     List<Example> findAllByIdList(List<String> ids);
          43 
          44     /** param condition */
          45     @Arguments( { "ids" })
          46     @Query("1 != 0 " //
          47             + "/*IF ids != null && ids.size() > 0*/" //
          48             + "AND ID IN /*ids*/('') " //
          49             + "/*END*/")
          50     List<Example> findAllByIdListAdv(List<String> ids);
          51 
          52     // U////////////////////////////////////
          53     /** update */
          54     int updateExample(Example exp);
          55 
          56     /** object param */
          57     @Sql("UPDATE EXAMPLE SET NAME = /*exp.name*/ ")
          58     int updateExampleName(Example exp);
          59 
          60     // D////////////////////////////////////
          61     /** delete */
          62     int deleteExample(Example exp);
          63 
          64     /** delete by param */
          65     @Query("ID = ?")
          66     int deleteExampleById(String id);
          67 }
          @S2Dao指明了檢索對應的數據承接類。
          從幾個檢索函數可以看出,s2dao基本能實現所有種類的檢索。
          • @Query為條件注釋(如findAllByIdAndName),相當于where后面的。
          • 當檢索條件的參數需要反復使用或顛倒順序等的時候(如findAllById),需要添加@Arguments注釋。
          • @Sql則為原生態無污染的SQL代碼注釋(如findIDMax)。
          • 可以對輸入參數進行條件控制(如findAllByIdListAdv)。
          測試程序:
           1 private static void testBase() {
           2 
           3     ExampleDao dao = getComponent(ExampleDao.class);
           4 
           5     // C///////////////////////////////
           6     Example exp = new Example();
           7     exp.setId("1");
           8     exp.setName("a");
           9     System.out.println(dao.insertExample(exp));
          10     exp = new Example();
          11     exp.setId("2");
          12     exp.setName("b");
          13     System.out.println(dao.insertExample(exp));
          14 
          15     // R///////////////////////////////
          16     System.out.println(dao.findAll());
          17     System.out.println(dao.findAllByIdAndName("1""a"));
          18     System.out.println(dao.findAllById("1""2"));
          19     System.out.println(dao.findIDMax());
          20 
          21     List<String> ids = new ArrayList<String>();
          22     ids.add("1");
          23     ids.add("2");
          24     System.out.println(dao.findAllByIdList(ids));
          25     System.out.println(dao.findAllByIdListAdv(null));
          26     System.out.println(dao.findAllByIdListAdv(ids));
          27 
          28     // U///////////////////////////////
          29     exp = new Example();
          30     exp.setId("1");
          31     exp.setName("c");
          32     System.out.println(dao.updateExample(exp));
          33     exp = new Example();
          34     exp.setName("haha");
          35     System.out.println(dao.updateExampleName(exp));
          36 
          37     // D///////////////////////////////
          38     exp = new Example();
          39     exp.setId("1");
          40     exp.setName("a");
          41     System.out.println(dao.deleteExample(exp));
          42     exp = new Example();
          43     exp.setId("2");
          44     System.out.println(dao.deleteExample(exp));
          45 }
          46 
          47 public static <T> T getComponent(final Class<T> clazz) {
          48     final S2Container container = SingletonS2ContainerFactory.getContainer();
          49     final Object o = container.getComponent(clazz);
          50     final T bean = clazz.cast(o);
          51     return bean;
          52 }
          ※注:在執行測試前,需要進行框架的初始化,其實就是一行:
          SingletonS2ContainerFactory.init();

          執行結果當然是OK,控制臺LOG就不貼了,貼一下生成的DB LOG,按測試代碼中調用dao函數的順序一一對應:
           1 INSERT INTO EXAMPLE (id, name) VALUES ('1''a')
           2 INSERT INTO EXAMPLE (id, name) VALUES ('2''b')
           3 SELECT EXAMPLE.id, EXAMPLE.name FROM EXAMPLE
           4 SELECT EXAMPLE.id, EXAMPLE.name FROM EXAMPLE WHERE ID = '1' AND NAME = 'a'
           5 SELECT EXAMPLE.id, EXAMPLE.name FROM EXAMPLE WHERE ID = '2' OR ID = '1'
           6 SELECT MAX(E.ID) FROM EXAMPLE E
           7 SELECT EXAMPLE.id, EXAMPLE.name FROM EXAMPLE WHERE ID IN ('1''2')
           8 SELECT EXAMPLE.id, EXAMPLE.name FROM EXAMPLE WHERE 1 != 0
           9 SELECT EXAMPLE.id, EXAMPLE.name FROM EXAMPLE WHERE 1 != 0 AND ID IN ('1''2')
          10 UPDATE EXAMPLE SET name = 'c' WHERE id = '1'
          11 UPDATE EXAMPLE SET NAME = 'haha'
          12 DELETE FROM EXAMPLE WHERE id = '1'
          13 DELETE FROM EXAMPLE WHERE id = '2'

          2.多表

           1 package com.hg.s2dao.dto;
           2 
           3 import org.seasar.dao.annotation.tiger.Bean;
           4 
           5 @Bean(table = "FATHER")
           6 public class Father {
           7 
           8     private String id;
           9     private String name;
          10 
          11     public String getId() {
          12         return id;
          13     }
          14 
          15     public void setId(String id) {
          16         this.id = id;
          17     }
          18 
          19     public String getName() {
          20         return name;
          21     }
          22 
          23     public void setName(String name) {
          24         this.name = name;
          25     }
          26 
          27 }

           1 package com.hg.s2dao.dto;
           2 
           3 import org.seasar.dao.annotation.tiger.Bean;
           4 import org.seasar.dao.annotation.tiger.Relation;
           5 
           6 @Bean(table = "CHILD")
           7 public class Child {
           8 
           9     private String id;
          10     private String name;
          11     private Father father;
          12     /* s2dao do not support cascade CUD but only R,so need field 'fId' */
          13     private String fId;
          14 
          15     public String getId() {
          16         return id;
          17     }
          18 
          19     public void setId(String id) {
          20         this.id = id;
          21     }
          22 
          23     public String getName() {
          24         return name;
          25     }
          26 
          27     public void setName(String name) {
          28         this.name = name;
          29     }
          30 
          31     public String getFId() {
          32         return fId;
          33     }
          34 
          35     public void setFId(String id) {
          36         fId = id;
          37     }
          38 
          39     @Relation(relationNo = 0, relationKey = "F_ID:ID")
          40     public Father getFather() {
          41         return father;
          42     }
          43 
          44     /* cannot del this method */
          45     public void setFather(Father father) {
          46         this.father = father;
          47     }
          48 
          49 }
          Father和Child存在一對多/一對一關聯,Child中維持著與Father的關系。
          看到這你可能會很奇怪,為什么要存在fId字段?不是有Father類了么?遺憾的是,目前s2dao不支持級聯的插入更新刪除(CUD),只支持級聯檢索。fId是為了CUD而存在的。
          實現級聯檢索的是Child.java中的getFather方法,@Relation指明了其關系。relationNo為是第幾個外鍵關聯的序號,relationKey為主外鍵名稱聲明。

           1 package com.hg.s2dao.dao;
           2 
           3 import org.seasar.dao.annotation.tiger.S2Dao;
           4 
           5 import com.hg.s2dao.dto.Father;
           6 
           7 @S2Dao(bean = Father.class)
           8 public interface FatherDao {
           9 
          10     /** insert single */
          11     int insert(Father f);
          12 
          13     /** delete */
          14     int delete(Father c);
          15 }

           1 package com.hg.s2dao.dao;
           2 
           3 import org.seasar.dao.annotation.tiger.Query;
           4 import org.seasar.dao.annotation.tiger.S2Dao;
           5 
           6 import com.hg.s2dao.dto.Child;
           7 
           8 @S2Dao(bean = Child.class)
           9 public interface ChildDao {
          10 
          11     /** insert single */
          12     int insert(Child c);
          13 
          14     /** contains condition */
          15     // cannnot only write: @Query("ID = ?")
          16     @Query("CHILD.ID = ?")
          17     Child findAllById(String id);
          18 
          19     /** update */
          20     int update(Child c);
          21 
          22     /** delete */
          23     int delete(Child c);
          24 
          25 }

          測試程序:
           1 private static void testRelation() {
           2 
           3     FatherDao daoF = getComponent(FatherDao.class);
           4     ChildDao daoC = getComponent(ChildDao.class);
           5 
           6     // C///////////////////////////////
           7     Father popeye = new Father();
           8     popeye.setId("1");
           9     popeye.setName("Popeye");
          10     System.out.println(daoF.insert(popeye));
          11 
          12     Child pipeye = new Child();
          13     pipeye.setId("1");
          14     pipeye.setName("Pipeye");
          15     pipeye.setFId(popeye.getId());
          16     System.out.println(daoC.insert(pipeye));
          17 
          18     Child pupeye = new Child();
          19     pupeye.setId("2");
          20     pupeye.setName("Pupeye");
          21     pupeye.setFId(popeye.getId());
          22     System.out.println(daoC.insert(pupeye));
          23 
          24     // R///////////////////////////////
          25     // pipeye.getFather() is null,so need search again
          26     Child pipeyeNew = daoC.findAllById(pipeye.getId());
          27     System.out.println(pipeyeNew.getFather());
          28 
          29     // U///////////////////////////////
          30     pipeyeNew.setName("pipeyeNew");
          31     System.out.println(daoC.update(pipeyeNew));
          32 
          33     // D///////////////////////////////
          34     System.out.println(daoC.delete(pipeye));
          35     System.out.println(daoC.delete(pupeye));
          36     System.out.println(daoF.delete(popeye));
          37 }

          執行結果DB LOG:
          1 INSERT INTO FATHER (id, name) VALUES ('1''Popeye')
          2 INSERT INTO CHILD (id, f_id, name) VALUES ('1''1''Pipeye')
          3 INSERT INTO CHILD (id, f_id, name) VALUES ('2''1''Pupeye')
          4 SELECT CHILD.id, CHILD.f_id, CHILD.name, father.id AS id_0, father.name AS name_0 FROM CHILD, FATHER father WHERE CHILD.F_ID = father.ID(+AND CHILD.ID = '1'
          5 UPDATE CHILD SET f_id = '1', name = 'pipeyeNew' WHERE id = '1'
          6 DELETE FROM CHILD WHERE id = '1'
          7 DELETE FROM CHILD WHERE id = '2'
          8 DELETE FROM FATHER WHERE id = '1'


          除以上功能,s2dao還可以調用存儲過程,這里就不再介紹了。
          posted on 2009-05-07 17:08 Atea 閱讀(856) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 永昌县| 南召县| 柳林县| 娱乐| 双江| 固安县| 池州市| 濮阳县| 麻江县| 天全县| 彰武县| 乐都县| 佛冈县| 乌拉特前旗| 营山县| 康保县| 元阳县| 澎湖县| 平和县| 新竹县| 永川市| 英超| 彭山县| 乐都县| 东乌珠穆沁旗| 灌云县| 城口县| 本溪| 闻喜县| 通江县| 礼泉县| 银川市| 隆德县| 阿拉尔市| 怀化市| 安阳县| 荣成市| 景德镇市| 吉林省| 阜康市| 封开县|