android平台db4o使用示例
db4o是一個純對象的數(shù)據(jù)庫,現(xiàn)支持java和.NET。07年的時候,db4objects宣布db4o已可以順利運行于Android平臺,當時db4objects公司和db4o的愛好者積極推進db4o運行于Google Android平臺,以期待讓db4o成為Android上的首選數(shù)據(jù)庫平臺,但令人遺憾的是google最后選擇了sqlite作為作為android平臺的數(shù)據(jù)庫。但是沒有關系,db4objects有相應的解決方案,db4o可以無縫的運行于Android。
相對于關系型數(shù)據(jù)庫,db4o還顯得很年輕。大家對關系型數(shù)據(jù)庫的理念根深蒂固,所以一時很難理解對象型數(shù)據(jù)庫的理論。現(xiàn)在的數(shù)據(jù)庫課程也都是以關系型數(shù)據(jù)庫為示例,對象型數(shù)據(jù)庫都是作為一個新興的數(shù)據(jù)庫一筆帶過。這也導致很多人缺乏對象型數(shù)據(jù)的理論知識。真的想用好db4o,對象型數(shù)據(jù)的理論知識是必不可少的。例如對象型數(shù)據(jù)是沒有主鍵這個概念的,這會讓大多數(shù)人難以適應。
db4o也發(fā)展了幾年了,到現(xiàn)在好多人還不知道,網(wǎng)上的資料比較少,也是比較老的版本。現(xiàn)在主流的android應用也都是使用sqlite數(shù)據(jù)庫,這肯定是有原因的。這倒不是性能上的問題。Db4o的速度不見得會比關系型數(shù)據(jù)庫慢。其最大的問題在于理解數(shù)據(jù)對象的關系和操作。db4o沒有看上去那么簡單,說實在的,我現(xiàn)在好多東西還沒搞明白。比如:
class A {int id;String name;List<B> list; }存儲這種結構的對象,我一直搞不明白A和B的關聯(lián)情況。對應一些大應用還是建議使用比較成熟的東西。Android平臺上大家倒是可以一試,我也分享下自己的學習成果。現(xiàn)在db4o最新是8.x。穩(wěn)定版本是7.x。本人以7.x演示。要說的是android平臺需要的db4o的jar要1M多(8.x版的要1.4M左右,網(wǎng)上說的400k應該是很早的版本了,官網(wǎng)上找不到了)。db4o的官網(wǎng)下載地址http://community.versant.com/Downloads/db4o.aspx。對應android開發(fā)只需要核心jar包db4o-7.x-core-java5.jar。在下載的壓縮包里還有一個db4o數(shù)據(jù)庫的視圖工具OME(ObjectManager Enterprise),這是一個eclipse插件,是一個離線的安裝包。
Db4o的操作流程很簡單:打開數(shù)據(jù)庫文件,通過DAO讀寫數(shù)據(jù),最后關閉數(shù)據(jù)庫,支持事務和并發(fā)。
作為對象型數(shù)據(jù)庫是不用寫sql的,這點很爽。
?
對于db4o的基本操作不再多說,可以參考文章最后的參考鏈接。我做了一些封裝,并使用泛型來減少Dao的創(chuàng)建。如果不使用本例的泛型的話,你需要對每個bean創(chuàng)建Dao,如UserDao、CacheDao。在關系型數(shù)據(jù)庫中我們通過主鍵來識別一條記錄,但是對象型數(shù)據(jù)庫中沒有記錄,只有對象。db4o通過序列化java對象并存入文件,它識別是這個還是那個對象用的不是主鍵,而是UUID,這個UUID只有當一個對象被存入數(shù)據(jù)庫中才會被分配到,未存入數(shù)據(jù)庫的對象是沒有UUID的,所以說我們并不能通過UUID來更新一條數(shù)據(jù).那怎樣更新一條數(shù)據(jù)?我們只能是先將這個對象查出來,然后修改內(nèi)容再存入,或者查詢到直接刪除,然后存入新對象.
Db.java
package com.sljm.lfa.store;import java.io.Serializable; import java.util.ArrayList; import java.util.List;import com.db4o.Db4oEmbedded; import com.db4o.ObjectContainer; import com.db4o.ObjectSet; import com.db4o.config.CommonConfiguration; import com.db4o.config.EmbeddedConfiguration; import com.db4o.query.Query;/*** @author SunnyCoffee* @date 2013-9-7* @version 1.0* @desc DB配置和操作接口*/ public class Db<T extends Serializable> {private Class<T> clazz;private String unique;private static ObjectContainer db;/*** 這里的unique是class里作為索引的屬性* * @param clazz* @param unique*/public Db(Class<T> clazz, String unique) {this.clazz = clazz;this.unique = unique;}// 打開數(shù)據(jù)庫private ObjectContainer getDb() {if (db == null || db.ext().isClosed()) {db = Db4oEmbedded.openFile(conf(), getDbPath());}return db;}private String getDbPath() {return "/mnt/sdcard/lfa.db4o";// 數(shù)據(jù)庫文件的路徑}// 數(shù)據(jù)庫的參數(shù)配置. 數(shù)據(jù)庫配置并沒有存儲到文件,每次打開數(shù)據(jù)庫執(zhí)行此方法進行配置private EmbeddedConfiguration conf() {EmbeddedConfiguration conf = Db4oEmbedded.newConfiguration();CommonConfiguration common = conf.common();if (unique != null) {common.objectClass(clazz).objectField(unique).indexed(true);}common.objectClass(clazz).cascadeOnUpdate(true);common.objectClass(clazz).cascadeOnActivate(true);return conf;}/*** 存儲對象* * @param obj*/public void store(T obj) {if (obj == null) {return;}getDb().store(obj);}public void store(List<T> list) {if (list == null) {return;}for (T t : list) {getDb().store(t);}}/*** 刪除對象* * @param obj*/public void delete(T obj) {if (obj == null) {return;}getDb().delete(obj);}public void delete(List<T> list) {if (list == null) {return;}for (T t : list) {getDb().delete(t);}}/*** 查詢所有的某一對象* * @return*/public List<T> queryAll() {Query query = getDb().query();query.constrain(clazz);query.descend(unique).orderAscending();ObjectSet<T> set = query.execute();List<T> list = fromObjectSet(set);return list;}/*** 根據(jù)id查詢一個對象* * @param field* 字段* @param id* 字段的值* @return*/public T queryById(Object id) {List<T> list = queryWhere(unique, id);if (list.size() == 0) {return null;}return list.get(0);}public List<T> queryWhere(String field, Object value) {Query query = getDb().query();query.constrain(clazz);query.descend(field).constrain(value);ObjectSet<T> set = query.execute();List<T> list = fromObjectSet(set);return list;}public void close() {getDb().commit();if (db != null) {db.close();db = null;}}private List<T> fromObjectSet(ObjectSet<T> set) {List<T> list = new ArrayList<T>();while (set.hasNext()) {list.add(set.next());}return list;} }db4o有3種查詢方式,官方一直推薦NQ(Native Queries),也就是原生查詢.首先它是類型安全的,其次查詢支持本地語言。還有就是QBE(Query by Example)和SODA(Simple Object Database Access)。QBE沒有用過,似乎沒什么特點。SODA的是最低層的查詢方式,速度快、靈活性高,不足之處就是非類型安全的。本例中因為有排序操作,考慮效率和易用性上使用了SODA。
DbApiImpl.java
package com.sljm.lfa.store;import java.util.List;import com.sljm.lfa.bean.Cache;/*** @author SunnyCoffee* @date 2013-10-22* @version 1.0* @desc 數(shù)據(jù)庫接口實現(xiàn)類,查詢使用SODA。 NQ查詢更安全,考慮到效率和簡單使用了SODA,* 如此一來必須使用字符串來表示字段,如果javaBean變動這里字段必須做調(diào)整*/ public class DbApiImpl implements DbApi {public Cache getCacheById(final String id) {Db<Cache> db = new Db<Cache>(Cache.class, "id");Cache cache = db.queryById(id);db.close();return cache;}public void updateCache(Cache cache) {Db<Cache> db = new Db<Cache>(Cache.class, "id");Cache c = db.queryById(cache.getId());db.delete(c);db.store(cache);db.close();}public void clearCache() {Db<Cache> db = new Db<Cache>(Cache.class, "id");List<Cache> list = db.queryAll();db.delete(list);db.close();} }
這里注意兩點一個是Serializable接口,一個是空構造方法。
Cache.java
package com.sljm.lfa.bean;import java.io.Serializable;/*** @author SunnyCoffee* @create 2013-8-21* @version 1.0* @desc 緩存bean*/ public class Cache implements Serializable {/*** */private static final long serialVersionUID = 1L;private String id;private long lastModified;private long valid;private Object result;public Cache() {}// set and get }
參考鏈接:
http://www.ibm.com/developerworks/cn/java/j-db4o/
http://www.db4o.com
總結
以上是生活随笔為你收集整理的android平台db4o使用示例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一款由React Native编写的开源
- 下一篇: 曼联输的体无完肤