DBMNG数据库管理与应用

书籍是全世界的营养品。生活里没有书籍,就好像没有阳光;智慧里没有书籍,就好像鸟儿没有翅膀。
当前位置:首页 > 数据库基础 > DB4O

Db4O数据库之运用

文/junglesong


注:欢迎与我讨论(junglesong@gmail.com)


Db4O全名DataBase For Object,是一个对象数据产品,它的数据输入输出全是对象,完全消除了以前面向对象的系统和关系型数据库之间阻抗不匹配的问题,也省却了OR Mapping工具的烦琐配置,是我们更能把注意力集中到项目上.关于Db4O的细节可以参考这个网址:http://developer.db4o.com/blogs/chinese/,或者直接去其大本营http://www.db4o.com/.


一.如何在项目中使用Db4O.
这非常简单,到Db4O大本营http://www.db4o.com/下载最新的开发包并加入自己的Lib即可,我选择的是db4o-5.2-java1.2.jar.
以下将对我在项目中使用Db4O的过程进行一下讲述.


二.构建DataBaseForObject基本类.
构建DataBaseForObject基本类的基本目的是为调用DB4O的个个Service类提供统一的借口,它是Adapter模式的一种体现.
此外,为加快查询速度,我还加入了Jakerta的对象池支持.
public class Db4OFactory implements PoolableObjectFactory {
private static String DataFilePath = "";


public static final String DataFileName = "DBFile.dat";


public Object makeObject() throws Exception {
Object obj = Db4o.openFile(DataFilePath);
//System.err.println("Making Object " + obj);
return obj;
}


public void activateObject(Object obj) throws Exception {
//System.err.println("Activating Object " + obj);
}


public void passivateObject(Object obj) throws Exception {
//System.err.println("Passivating Object " + obj);
}


public boolean validateObject(Object obj) {
return true;
}


public void destroyObject(Object obj) throws Exception {
ObjectContainer db=(ObjectContainer)obj;
db.close();
//System.err.print ln("Destroying Object " + obj);
}




public static void setDataFilePath(String dataFilePath) {
DataFilePath = dataFilePath;
}


public static String getDataFilePath() {
return DataFilePath;
}
}


下面是其主要方法:
public class DataBaseForObject {
// 删除一个对象
public static synchronized void remove(Db4OStorable obj) {
PoolableObjectFactory factory = new Db4OFactory();
ObjectPool pool = new StackObjectPool(factory);
ObjectContainer db = null;


try {
db = (ObjectContainer) pool.borrowObject();


Query query = db.query();
query.descend("id").constrain(obj.getId());


ObjectSet objSet = query.execute();
if (objSet.hasNext()) {
db.delete(objSet.next());
}


db.commit();
db = null;


} catch (Exception e) {
System.out.println("从Db4Obj数据库删除对象错误!");
e.printStackTrace();
} finally {
try {
if (db != null) {// 避免将一个对象归还两次
pool.returnObject(db);
}
pool.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}


// 存储或更新一个对象
public static void save(Class objClass, Db4OStorable obj) {
PoolableObjectFactory factory = new Db4OFactory();
ObjectPool pool = new StackObjectPool(factory);
ObjectContainer db = null;


try {
db = (ObjectContainer) pool.borrowObject();


Query query = db.query();
query.constrain(objClass);
query.descend("id").constrain(obj.getId());


ObjectSet objSet = query.execute();


if (objSet.hasNext()) {
Db4OStorable found = (Db4OStorable) objSet.next();
found.update(obj);
db.set(found);
} else {
db.set(obj);
}
db.commit();
db = null;


} catch (Exception e) {
System.out.println("从Db4Obj数据库更新对象错误!");
e.printStackTrace();
} finally {
try {
if (db != null) {// 避免将一个对象归还两次
pool.returnObject(db);
}
pool.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}


// 进行对象查询
public static ArrayList searchBy(Predicate predicate) {
PoolableObjectFactory factory= new Db4OFactory();
ObjectPool pool = new StackObjectPool(factory); 
ObjectContainer db = null;


ArrayList retval = new ArrayList();


try {
db=(ObjectContainer)pool.borrowObject();


ObjectSet objSet= db.query(predicate);


while (objSet.hasNext()) {
Object obj = objSet.next();
retval.add(obj);
}


db=null;
} catch (Exception e) {
System.out.println("从Db4Obj数据库查询对象错误!");
e.printStackTrace();
} finally {
try {
if (db != null) {// 避免将一个对象归还两次
pool.returnObject(db);
}
pool.close();
} catch (Exception e) {
e.printStackTrace();
}
}


return retval;
}


}


使用这三个函数就可以对各种对象进行CRUD操作了.


为了区别同类型的不同对象,它们需要唯一的标志Id,所以我让每种需要进行持久化的类都实现了Db4OStorable接口,代码如下:
public interface Db4OStorable{
public String getId() ;
public void setId(String id) ; 
public void update(Object obj);
}


这样一来,各个类就有了统一的接口,代码就可以进行统一实现了,避免为一个类加一种判断.


二.构建各Service类.
为了实现对各种类型的不同处理,我们需要为每种对象提供一个Service类,让它来充当DB4O数据与对象之间的桥梁作用,这些类可以根据进行各种复杂的处理而不影响DataBaseForObject 的纯洁性.


下面是一个Service类的示例:


public class ProjectService{
public static boolean save(Project project) {
DataBaseForObject.save(Project.class,project); 
return true;
}


public static boolean delete(Project project){
project.getFile().delete();
DataBaseForObject.remove(project); 
return true;
}


public static Project getObjById(String id) {


final String Id=id;
Predicate predicate = new Predicate() {
public boolean match(Project prj) {
boolean retval = prj.getId().equals(Id);
return retval;
}
}; 


ArrayList list=DataBaseForObject.searchBy(predicate);


if(list.size()==0){
return null;
}


Project prj=(Project)list.get(0);
return prj;
}


public static ArrayList getAllDatum(Predicate predicate,SortBean sortBean){
ArrayList list=DataBaseForObject.searchBy(predicate);
Collections.sort(list,new ProjectComarator(sortBean));
return list;
}
}


可以看出,上述四个方法对于Project对象的CRUD操作更加方便了.


三.对象的具体操作.
1)Create创建操作
Project project=new Project();
project.setId(Util.getIdbyTime());// 注意这里是根据时间取出唯一ID,还可以有别的规则
project.setXXX(xxx);
.......
ProjectService.save(project);


2)Delete删除操作
ProjectService.delete(project);


3)Update更新操作
project.setXXX(xxx);
.......
ProjectService.save(project);
这里要多说几句,更新操作首先要ID一致,这里就不能改编ID值,否则就变成了创建;其次更新操作依赖于对象对Db4OStorable的update方法的实现,彻底更新一个对象需要用新对象的所有成员替代旧对象的所有成员,下面是我的一个实现例子:
public void update(Object obj){
Project another=(Project)obj;


this.id=another.id;
this.pid=another.pid;
this.path=another.path;
this.title=another.title;
this.type=another.type;
this.status=another.status;
this.concept=another.concept; 
this.creator=another.creator; 
this.chief=another.chief;
this.members=another.members; 
this.file=another.file; 
}
这个方法没实现完全的话,对象不能完全更新,切记.


4)Search查询操作.
DB4O提供了多种查询方式,经过一段时间后我决定采用精确灵活的predicate查询方式,
请看其使用:
Predicate myprojectsPredicate = new Predicate() {
public boolean match(Project prj) {
boolean retval = true;


retval = retval
&& (prj.getType().equals(Consts.ProjectType_Project));
retval = retval && (prj.getPid().equals("0"));
retval = retval
&& (prj.getChief().equals(Username) || Util.strContain(
prj.getMembers(), Username));


return retval;
}
};
ArrayList projectResult = (ArrayList) ProjectService.getAllDatum(myprojectsPredicate, new SortBean("title","asc"));


很明显,由于查询方式是Java语言,它更自然,易懂和容易修改,而且不会把业务耦合到SQL中,相对冗长复杂的SQL要强很多,比HibernateHQL也简单不少.
不过美中不足的是数据的排序,我们需要一个实现了Comparator接口的类来实现排序,下面是我的实现过程,如果你对Comparator比较熟悉的话可以掠过.
你也可以不写得这样负复杂.


public class SortBean{
private String field;
private String order;


public SortBean(String field,String order){
this.field=field;
this.order=order;
}


public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public String getOrder() {
return order;
}
public void setOrder(String order) {
this.order = order;
}
}


public final class ProjectComarator implements Comparator{
private SortBean sortBean; 


public ProjectComarator(SortBean sortBean){
this.sortBean=sortBean;
}


public int compare(Object arg0, Object arg1) {
Project op1=(Project)arg0;
Project op2=(Project)arg1;


if(sortBean==null){
return op2.getId().compareTo(op1.getId());
}


if(sortBean.getField().equals("title") && sortBean.getOrder().equals("asc")){
return op1.getTitle().compareTo(op2.getTitle());
}
else if(sortBean.getField().equals("title") && sortBean.getOrder().equals("desc")){
return op2.getTitle().compareTo(op1.getTitle());
}
else if(sortBean.getField().equals("type") && sortBean.getOrder().equals("asc")){
return op1.getType().compareTo(op2.getType());
}
else if(sortBean.getField().equals("type") && sortBean.getOrder().equals("desc")){
return op2.getType().compareTo(op1.getType());
}
else if(sortBean.getField().equals("status") && sortBean.getOrder().equals("asc")){
return op1.getStatus().compareTo(op2.getStatus());
}
else if(sortBean.getField().equals("status") && sortBean.getOrder().equals("desc")){
return op2.getStatus().compareTo(op1.getStatus());
}
else if(sortBean.getField().equals("concept") && sortBean.getOrder().equals("asc")){
return op1.getConcept().compareTo(op2.getConcept());
}
else if(sortBean.getField().equals("concept") && sortBean.getOrder().equals("desc")){
return op2.getConcept().compareTo(op1.getConcept());
}
else if(sortBean.getField().equals("creator") && sortBean.getOrder().equals("asc")){
return op1.getCreator().compareTo(op2.getCreator());
}
else if(sortBean.getField().equals("creator") && sortBean.getOrder().equals("desc")){
return op2.getCreator().compareTo(op1.getCreator());
}
else if(sortBean.getField().equals("chief") && sortBean.getOrder().equals("asc")){
return op1.getChief().compareTo(op2.getChief());
}
else if(sortBean.getField().equals("chief") && sortBean.getOrder().equals("desc")){
return op2.getChief().compareTo(op1.getChief());
}
else if(sortBean.getField().equals("members") && sortBean.getOrder().equals("asc")){
return op1.getMembers().compareTo(op2.getMembers());
}
else if(sortBean.getField().equals("members") && sortBean.getOrder().equals("desc")){
return op2.getMembers().compareTo(op1.getMembers());
}
else if(sortBean.getField().equals("id") && sortBean.getOrder().equals("asc")){
return op1.getId().compareTo(op2.getId());
}
else if(sortBean.getField().equals("id") && sortBean.getOrder().equals("desc")){
return op2.getId().compareTo(op1.getId());
}
else{
return op2.getId().compareTo(op1.getId());
}
}


public SortBean getSortBean() {
return sortBean;
}


public void setSortBean(SortBean sortBean) {
this.sortBean = sortBean;

}


从以上查询代码可以看出,我们的业务全都在Java语言中实现,不需要Sql语句.这对系统的可移植性可修改性都有很好的帮助.




上面就是我在当前项目中使用DB4O对象数据库的全部过程,请大家多批评指教.
本站文章内容,部分来自于互联网,若侵犯了您的权益,请致邮件chuanghui423#sohu.com(请将#换为@)联系,我们会尽快核实后删除。
Copyright © 2006-2023 DBMNG.COM All Rights Reserved. Powered by DEVSOARTECH            豫ICP备11002312号-2

豫公网安备 41010502002439号