Just Java IT

          西門町學士關于Java的隨便一說而已……

          對象數據庫(ODBMS) db4o試用(Java version)

          我覺得我現在中了兩種毒:Java和SQL。西諺有云:When you have a hammer, everything looks like a nail。只要動手寫程序,頭腦中不自覺地就public class...其實很多時候一兩行簡短的scripts就可以了,即使像在Windows上,我們也可以寫jscript、wsh腳本。而在資料儲存 上,關系數據庫更是不二法寶。拿到一個項目,我馬上就要將它分解成各個Table,我覺得SQL是如此強大和靈活,以至于一見到O/R映射就覺得厭惡,直 到現在我也沒有碰過Hibernate。
          呵呵,抱怨了半天,與其在O/R映射中苦苦掙扎,不如跳出來看看其它的風景,比如:ODBMS(對象數據庫)。學士剛下載了db4o這個所謂對象數據庫,試著玩了一下,雖尚不知味之甘苦,勉得以一窺豹斑。
          db4o 目前是Version 5.0,僅需要一個jar文件,我用的支持JDK5的那個:db4o-5.0-java5.jar; 你如果用的其它版本的JDK,有相對應的jar文件。這個jar文件就是數據庫,可不要想象成JDBC Driver之類的東東,JDBC Driver是RDBMS(關系數據庫)才需要的東東,呵呵。
          好了,閑話不說,我們現在試試這個ODBMS。首先,建一個你想要保存的對象,我寫了一個非常簡單的Student.java:

          public class Student {
              private String name;
              private int points;
             
             
              /** Creates a new instance of Student */
              public Student(String name, int points) {
                  this.name = name;
                  this.points = points;
              }
             
              public String getName() {
                  return name;
              }
             
              public int getPoints() {
                  return points;
              }
             
              public void addPoints(int points) {
                  this.points += points;
              }
             
              public String toString() {
                  return name + "/" + points;
              }
          }

          這個類非常簡單,只有兩個instance fields,學生姓名和分數,以及一些簡單的methods,完全沒有用任何跟db4o相關的代碼。然后我們就可以將Student的實例放入數據庫操作了:InsertObj2Db4o.java:

          import java.io.File;
          import java.util.List;

          import com.db4o.Db4o;
          import com.db4o.ObjectContainer;
          import com.db4o.ObjectSet;
          import com.db4o.query.*;

          /**
           *
           * @author Stevech
           */
          public class InsertObj2Db4o {
             
              /** Creates a new instance of InsertObj2Db4o */
              public InsertObj2Db4o() {
              }
             
              public static void main(String[] args) {
                  ObjectContainer db = Db4o.openFile("student.yap");
                  try {
                      storeStudents(db);
                      retrieveAllStudents(db);
                      retrieveStudentByName(db);
                      retrieveStudentByPoints(db);
                      updateStudent(db);
                      deleteStudent(db);
                      descendStudents(db);
                      retrievePartStudents(db);
                  } finally {
                      db.close();
                  }
              }
             
              public static void storeStudents(ObjectContainer db) {
                  Student bg = new Student("Bill Gates", 119);
                  Student sm = new Student("Scott McNealy", 102);
                  Student sj = new Student("Steve Jobs", 150);
                  Student rs = new Student("Richard Stallman", 500);
                  Student le = new Student("Larry Elison", 105);
                  Student sc = new Student("Steve Cheng", 95);
                 
                  db.set(bg);
                  db.set(sm);
                  db.set(sj);
                  db.set(rs);
                  db.set(le);
                  db.set(sc);
                 
                  System.out.println("Added " + bg + ", " + sm + ", " + sj);
                  System.out.println("Added " + rs + ", " + le + ", " + sc);
              }
             
              public static void retrieveAllStudents(ObjectContainer db) {
                  ObjectSet<Student> result = db.get(Student.class);
                  listResult(result);
              }
             
              public static void retrieveStudentByName(ObjectContainer db) {
                  Student proto = new Student("Bill Gates", 0); // Note: 0 is  default value for int
                  ObjectSet<Student> result = db.get(proto);
                  listResult(result);
              }
             
              public static void retrieveStudentByPoints(ObjectContainer db) {
                  Student proto = new Student(null, 500);
                  ObjectSet<Student> result = db.get(proto);
                  listResult(result);
              }
             
              public static void updateStudent(ObjectContainer db) {
                  ObjectSet<Student> result = db.get(new Student("Steve Cheng", 95));
                  Student found = result.next();
                  found.addPoints(10);
                  db.set(found);
                  retrieveAllStudents(db);
                  System.out.println("Added 10 points for " + found);
              }
             
              public static void deleteStudent(ObjectContainer db) {
                  ObjectSet<Student> result = db.get(new Student("Steve Cheng", 0));
                  Student found = result.next();
                  db.delete(found);
                  retrieveAllStudents(db);
                  System.out.println("Deleted " + found);
              }
             
              public static void descendStudents(ObjectContainer db) {
                  Query query = db.query();
                  query.constrain(Student.class);
                  Query descendQuery = query.descend("points").orderDescending();
                  ObjectSet<Student> result = query.execute();
                  listResult(result);
              }
             
              public static void retrievePartStudents(ObjectContainer db) {
                  List<Student> result = db.query(new Predicate<Student>() {
                      public boolean match(Student s) {
                          return s.getPoints() > 120 && s.getPoints() < 500 || s.getName().equals("Bill Gates");
                      }
                  });
                  listResult(result);
              }
             
              public static void listResult(ObjectSet result) {
                  //System.out.println(result.size());
                  System.out.println("************************************");
                  while(result.hasNext()) {
                      System.out.println(result.next());
                  }
              }
             
              public static void listResult(java.util.List result){
                  //System.out.println(result.size());
                  System.out.println("************************************");
                  for(int x = 0; x < result.size(); x++)
                      System.out.println(result.get(x));
              }   
          }

          我們一點一點地看:
          首 先,與RDBMS一樣,我們需要連接到數據庫。db4o可以運行為C/S模式(或者叫Remote模式,就像Oracle, PostgreSQL, MSSQLSERVER, etc),也可以是local模式(或者叫embed模式)。Borland的JDataStore也與此相似,不同的是JDataStore是 RDBMS。我們這里用local模式:

                  ObjectContainer db = Db4o.openFile("student.yap");

          它打開當前目錄下的student.yap文件(也即數據庫文件),如果沒有,就自動新建一個。然后,就該往里面添數據了:(storeStudents method)

                  Student bg = new Student("Bill Gates", 119);
              ...
                  db.set(bg);

          非常地簡單。
          同樣,取出數據也是一樣地簡單:(retrieveAllStudents method)

                  ObjectSet<Student> result = db.get(Student.class);

          先告訴db(一個ObjectContainer實例)我們要取出數據的類型是Student,然后所有的Student類型的數據就存在ObjectSet中了。
          現實中,絕大多數時候我們只對那些滿足特定條件的數據感興趣,比如說,我們對Bill Gates同學有極大的興趣:(retrieveStudentByName method)

                  Student proto = new Student("Bill Gates", 0); // Note: 0 is  default value for int
                  ObjectSet<Student> result = db.get(proto);

          我 們先建立一個Student的模板,name為Bill Gates,而points為任意值。然后將這個模板遞給db即可。值得注意的是這里points值為0,這并不是我們希望Bill Gates同學的分數為鴨蛋,而僅僅因為0是int的默認值,如果這個參數是Object類型,我們這里就會賦予它默認值null(參見 retrieveStudentByPoints method)當指定的參數為默認值時,意味著我們不對它進行任何限制。這給做模板的方法在db4o中稱作QBE (Query by Example),由于顯而易見的缺點,實際上往往我們使用的是另一種稱作Native Queries的方法來選取數據(見后面retrievePartStudents method)
          現在,我們覺得Steve Cheng同學太可憐了,因為只有他的分數在100以下,因此我們決定給他加上10分(上帝保佑你碰到這樣的教師):(updateStudent method)

                  ObjectSet<Student> result = db.get(new Student("Steve Cheng", 95));
                  Student found = result.next();
                  found.addPoints(10);
                  db.set(found);

          我 們先將Steve Cheng從數據庫中取出來放在一個名為found的Student對象中,然后調用Student的instance method: addPoints(int points)來給found加上10分。然后,將found重新放入db中。這就完成了更新操作。
          我 們再來看看這個班級里的學生。“Oh, my God!” 有人合不上嘴了,“這個班里全是大腕兒級的人物!But wait, 這個叫Steve Cheng的是什么東西啊?竟然跟Bill Gates (RMS,如果說話的人是GNU fellow的話)列在一起。強烈要求廢了他!!”顧客就是上帝,我們只得對不起Steve Cheng了,將他從數據庫中刪除:(deleteStudent method)

                  ObjectSet<Student> result = db.get(new Student("Steve Cheng", 0));
                  Student found = result.next();
                  db.delete(found);

          與更新類似,我們先得選出Steve Cheng放到found對象中,然后,db.delete(found),Steve Cheng就從這個子虛烏有的班級中消失了。
          好了,剩下的都是英雄好漢,我們按他們各自的分數來給他們排座次(這至少比梁山好漢搞天降蝌蚪文排座次公平):(descendStudents method)

                  Query query = db.query();
                  query.constrain(Student.class);
                  Query descendQuery = query.descend("points").orderDescending();
                  ObjectSet<Student> result = query.execute();

          這里的做法不同于QBE或是Native Queriy,叫做SODA Query,是屬于比較底層的方法,但還是很容易看明白的。雖然沒有Native Queriy那么易于使用,但功能卻是很強大的。因此在實際中一些地方還是需要用到SODA Query的。
          排 了座次,我們要從精英之中選幸運兒去參加由HAL公司贊助的夏令營活動了,只有那些成績介于120到500之間的才能獲得這個天上掉的餡兒餅,(< 500,這不是明顯排斥RMS嘛),不過只要你是Bill Gates則不管你成績如何你都能撿這個餡兒餅吃(??):(retrievePartStudents method)

                  List<Student> result = db.query(new Predicate<Student>() {
                      public boolean match(Student s) {
                          return s.getPoints() > 120 && s.getPoints() < 500 || s.getName().equals("Bill Gates");
                      }
                  });

          這是一個典型的Native Query(這可是db4o大書特書引以為傲的東東),Predicate是定義在import com.db4o.query.*里的一個抽象類:
                  public abstract class Predicate<ExtentType>extends java.lang.Objectimplements java.io.Serializable
          定 義了public abstract boolean match(ExtentType candidate)方法。如果這個方法返回true,則candidate被放入result中。而條件語句也是標準的Java語句(如果使用.Net 則是標準的.Net語句)(而不是像RDBMS的SQL),這也是db4o自豪的地方。
          更多有關db4o的消息,請訪問http://www.db4o.com

          posted on 2006-01-04 22:10 西門町學士 閱讀(338) 評論(0)  編輯  收藏 所屬分類: Java


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


          網站導航:
           
          主站蜘蛛池模板: 石泉县| 石家庄市| 余干县| 登封市| 淄博市| 贵州省| 塔河县| 南陵县| 镇安县| 宾川县| 甘谷县| 乌鲁木齐市| 庆云县| 新安县| 来凤县| 定南县| 江西省| 秦皇岛市| 景东| 沙雅县| 沾益县| 高唐县| 墨江| 文登市| 井冈山市| 中超| 宣城市| 荃湾区| 张家界市| 商都县| 株洲市| 东乡族自治县| 萨迦县| 五台县| 咸宁市| 沙湾县| 徐汇区| 朝阳县| 新巴尔虎右旗| 苍梧县| 利川市|