您的位置:首页 > 移动开发 > Android开发

android平台db4o使用示例

2013-11-09 22:19 471 查看
db4o是一个纯对象的数据库,现支持java和.NET。07年的时候,db4objects宣布db4o已可以顺利运行于Android平台,当时db4objects公司和db4o的爱好者积极推进db4o运行于Google Android平台,以期待让db4o成为Android上的首选数据库平台,但令人遗憾的是google最后选择了sqlite作为作为android平台的数据库。但是没有关系,db4objects有相应的解决方案,db4o可以无缝的运行于Android。

相对于关系型数据库,db4o还显得很年轻。大家对关系型数据库的理念根深蒂固,所以一时很难理解对象型数据库的理论。现在的数据库课程也都是以关系型数据库为示例,对象型数据库都是作为一个新兴的数据库一笔带过。这也导致很多人缺乏对象型数据的理论知识。真的想用好db4o,对象型数据的理论知识是必不可少的。例如对象型数据是没有主键这个概念的,这会让大多数人难以适应。
db4o也发展了几年了,到现在好多人还不知道,网上的资料比较少,也是比较老的版本。现在主流的android应用也都是使用sqlite数据库,这肯定是有原因的。这倒不是性能上的问题。Db4o的速度不见得会比关系型数据库慢。其最大的问题在于理解数据对象的关系和操作。db4o没有看上去那么简单,说实在的,我现在好多东西还没搞明白。比如:
class A {
	int id;
	String name;
	List<B> list;
}

存储这种结构的对象,我一直搞不明白A和B的关联情况。对应一些大应用还是建议使用比较成熟的东西。Android平台上大家倒是可以一试,我也分享下自己的学习成果。现在db4o最新是8.x。稳定版本是7.x。本人以7.x演示。要说的是android平台需要的db4o的jar要1M多(8.x版的要1.4M左右,网上说的400k应该是很早的版本了,官网上找不到了)。db4o的官网下载地址http://community.versant.com/Downloads/db4o.aspx。对应android开发只需要核心jar包db4o-7.x-core-java5.jar。在下载的压缩包里还有一个db4o数据库的视图工具OME(ObjectManager
Enterprise),这是一个eclipse插件,是一个离线的安装包。



Db4o的操作流程很简单:打开数据库文件,通过DAO读写数据,最后关闭数据库,支持事务和并发。
作为对象型数据库是不用写sql的,这点很爽。

对于db4o的基本操作不再多说,可以参考文章最后的参考链接。我做了一些封装,并使用泛型来减少Dao的创建。如果不使用本例的泛型的话,你需要对每个bean创建Dao,如UserDao、CacheDao。在关系型数据库中我们通过主键来识别一条记录,但是对象型数据库中没有记录,只有对象。db4o通过序列化java对象并存入文件,它识别是这个还是那个对象用的不是主键,而是UUID,这个UUID只有当一个对象被存入数据库中才会被分配到,未存入数据库的对象是没有UUID的,所以说我们并不能通过UUID来更新一条数据.那怎样更新一条数据?我们只能是先将这个对象查出来,然后修改内容再存入,或者查询到直接删除,然后存入新对象.
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;
	}

	// 打开数据库
	private ObjectContainer getDb() {
		if (db == null || db.ext().isClosed()) {
			db = Db4oEmbedded.openFile(conf(), getDbPath());
		}
		return db;
	}

	private String getDbPath() {
		return "/mnt/sdcard/lfa.db4o";// 数据库文件的路径
	}

	// 数据库的参数配置. 数据库配置并没有存储到文件,每次打开数据库执行此方法进行配置
	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;
	}

	/**
	 * 根据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 数据库接口实现类,查询使用SODA。 NQ查询更安全,考虑到效率和简单使用了SODA,
 *       如此一来必须使用字符串来表示字段,如果javaBean变动这里字段必须做调整
 */
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: