linugb118--java space

Java

Object DataBase --DB4O之旅

Object DataBase --DB4O之旅

Object DataBase 出现有段时间了,最近对此有点兴趣,想探索一下,于是开始了我的db4o discovery 之旅。

db4o的jar 以及 api 在他document中都有写到, 其实他的 example 在document中也能找到,但是因为本人
也是在学习的过程,所以将用例也简单描述一下:

1.First Step:

define an object Class, this is Pilot object;

public class Pilot {  
  private String name;
  private int points;
 
  public Pilot(String name,int points) {
    this.name=name;
    this.points=points;
  }
   
  public int getPoints() {
    return points;
  }
 
  public void addPoints(int points) {
    this.points+=points;
  }
 
  public String getName() {
    return name;
  }
 
  public String toString() {
    return name+"/"+points;
  }
}

the next target is how to store, retrieve , update, delete the instance of the Pilot Class.

2.open database:

[accessDb4o]
ObjectContainer db=Db4o.openFile(Util.YAPFILENAME);
try {
// do something with db4o
}
finally {
db.close();
}

db4o 中通过创建一个file 来建立database,这是一个二进制文件。这里就是通过 Db4o.openFile(..)来得到一个 ObjectContainer instance.
ObjectContainer 就表示database。 实现对数据库的操作后, 可以通过 close,来release all resource。

3.store object

[storeFirstPilot]
Pilot pilot1=new Pilot("Michael Schumacher",100);
db.set(pilot1);
System.out.println("Stored "+pilot1);

只需要简单的调用set method 就可以了。

4.retrieve object

db4o 提供了三种 quering systems.
Query by Example (QBE)
Native Queries (NQ)
SODA Query API (SODA)

这里先介绍QBE:
首先需要构造你需要query 的对象的 prototype

To retrieve all pilots from our database, we provide an 'empty' prototype:
[retrieveAllPilots]
Pilot proto=new Pilot(null,0);
ObjectSet result=db.get(proto);
listResult(result);

public static void listResult(ObjectSet result) {
System.out.println(result.size());
while(result.hasNext()) {
System.out.println(result.next());
}

在 jdk 1.5中 可以这样写
List <Pilot> pilots = db.query(Pilot.class);

如果想查询 pilot name is Bobbi, 可以构造这样的prototype:
Pilot proto=new Pilot("Bobbi",0);

同样如果想查询 Point 是100的 可以这样 construct prototype:
Pilot proto=new Pilot(null,100);

5.update object

updating objects is just as easy as storing them,In fact, you can use retrieve a object and modify it, set it to database again.

[updatePilot]
ObjectSet result=db.get(new Pilot("Michael Schumacher",0));
Pilot found=(Pilot)result.next();
found.addPoints(11);
db.set(found);
System.out.println("Added 11 points for "+found);
retrieveAllPilots(db);

6. Delete objects
Objects are removed from the database using the delete() method.
[deleteFirstPilotByName]
ObjectSet result=db.get(new Pilot("Michael Schumacher",0));
Pilot found=(Pilot)result.next();
PDF by iText, generated by Doctor, courtesy of db4objects Inc.
db.delete(found);
System.out.println("Deleted "+found);

-------------------------------------------
Query:

对应数据库来说,Query是很复杂 很重要的。
刚才我们只是简单的 做了一个QBE的 introduce。现在我们来进一步学习db4o的Query

db4o 提供了三种 quering systems.
Query by Example (QBE) 表示简单的查询,只做简单的CRUD(Create Read Update Delete)
Native Queries (NQ) 接口层的调用,是db4o query的主要用法。
SODA Query API (SODA) 内部的接口层调用, 对db4o 更进一步的深入了解,可以做出更复杂的query,可以动态生成query

其实对应一般的数据库操作, 第二种 query (NQ) 才是最常用的。
NQ:
http://www.cs.utexas.edu/users/wcook/papers/NativeQueries/NativeQueries8-23-05.pdf
http://www.cs.utexas.edu/users/wcook/papers/SafeQuery/SafeQueryFinal.pdf
(所谓navtive queries 从字面上的意思,我们的查询可以通过native language 来query 数据,而不需要象传统的做法,需要develpment language
和 query language 两种语言来实现query。)
NQ 看上去也 传统的O/R mapping 看来,他更能进行对象直接的操作,但NQ 也有一个弊端,当我们需要检查一段很复杂的logic,如果我们是用的传统
的JDBC 我们可以找出query string 直接通过db UI Tool 去check logic 的正确性,但是如果是NQ 那就不行了, 我们需要运行这段code, 那当然需
要初始化涉及到的persistence Object, 这可能也是NQ 的很大的一个drawback。

SODA Query API:

The SODA query API is low level quering api, allowing direct access to nodes of query graphs. It can generate drynamic queries.

[retrieveAllPilots]
Query query=db.query();
query.constrain(Pilot.class);
ObjectSet result=query.execute();
listResult(result);

通过query method 来创建Query instance,然后通过 constrain instances 来 execute出 相应的result。
a query graph made up of query nodes and constraints. A query node is a placeholder for a
candidate object, a constraint decides whether to add or exclude candidates from the result.

////////////////////////////////
//Three query method example
///////////////////////////////

//QBE
just do CRUD simple operation, The code show above.

//NQ
public static void retrieveComplexNQ(ObjectContainer db) {
ObjectSet result=db.query(new Predicate() {
public boolean match(Pilot pilot) {
return pilot.getPoints()>99
&& pilot.getPoints()<199
|| pilot.getName().equals("Rubens Barrichello");
}
});
listResult(result);
}

//SODA
public static void retrieveComplexSODA(ObjectContainer db) {
Query query=db.query();
query.constrain(Pilot.class);
Query pointQuery=query.descend("points");
query.descend("name").constrain("Rubens Barrichello")
.or(pointQuery.constrain(new Integer(99)).greater()
.and(pointQuery.constrain(new
Integer(199)).smaller()));
ObjectSet result=query.execute();
listResult(result);
}
4.Structed Object

如果一个对象中不仅仅有常见的java类型还包含其他的对象,那么在modify 被包含的对象的时候,就会出现一个问题。如果我更新了这些被包含的对象,那么在update delete 的时候,他们会不会被操作到?db4o中 提供了一个 depth的概念。所有object 的默认的update depth为1,这就意味着该object 中的primitive 和 string members 能被update,其他类型的对象将不被upda
te。 同样对应delete 如果想实现 对象中的递归删除, 那同样需要利用db4o中的 delete depth


这是update depth:
[updatePilotSeparateSessionsImprovedPart1]
Db4o.configure().objectClass("com.db4o.f1.chapter2.Car")
.cascadeOnUpdate(true);

这是delete depth:
[deleteDeepPart1]
Db4o.configure().objectClass("com.db4o.f1.chapter2.Car")
.cascadeOnDelete(true);

Again: Note that all configuration must take place before the ObjectContainer is opened.

其实这里还没有结束,对于delete 会出现这么一个问题,当我通过 delet depth 将一个instance 删除了,他里面包含的某个其他类型的object instance 也被删除了,但是这个
对象还在被其他对象引用,那这个问题怎么办? 现在db4o 还没有解决方法。我们现在只能
小心操作delete。



5. Transactions
对应数据库来说,transaction 是必须的,下面我们来看看object dataBase--db4o是怎么
来处理transcation的。

当open a container的时候,一个transaction 就隐型地开始了,而当close 这个container,
那么当前的transaction就隐型地提交了。

那么如果显型地commit 和 rollback呢? 下面有这么两个例子:

public static void storeCarCommit(ObjectContainer db) {
Pilot pilot=new Pilot("Rubens Barrichello",99);
Car car=new Car("BMW");
car.setPilot(pilot);
db.set(car);
db.commit();
}


public static void storeCarRollback(ObjectContainer db) {
Pilot pilot=new Pilot("Michael Schumacher",100);
Car car=new Car("Ferrari");
car.setPilot(pilot);
db.set(car);
db.rollback();
}

与JDBC相比,好像有一个区别就是,db4o不需要来设置commit的模式, setAutoCommit()

她就是如果db.close(),那么就autoCommit了。

对于Object Database,因为他们都是用object 来存取,那么当object 被set 相应的值后,但没有save到database,也就说
current transaction 被rollback,那么为了保持数据的一致性,需要refresh live object.那么这个怎么来实现呢?

public static void carSnapshotRollbackRefresh(ObjectContainer db)
{
ObjectSet result=db.get(new Car("BMW"));
Car car=(Car)result.next();
car.snapshot();
db.set(car);
db.rollback();
PDF by iText, generated by Doctor, courtesy of db4objects Inc.
db.ext().refresh(car,Integer.MAX_VALUE);
System.out.println(car);
}

6.Embedded server
对应 Embedded server,open一个port为0的server。

[accessLocalServer]
ObjectServer server=Db4o.openServer(Util.YAPFILENAME,0);
try {
PDF by iText, generated by Doctor, courtesy of db4objects Inc.
ObjectContainer client=server.openClient();
// Do something with this client, or open more clients
client.close();
}
finally {
server.close();
}

7.Networking

[accessRemoteServer]
ObjectServer server=Db4o.openServer(Util.YAPFILENAME,PORT);
server.grantAccess(USER,PASSWORD);
try {
ObjectContainer
client=Db4o.openClient("localhost",PORT,USER,PASSWORD);
// Do something with this client, or open more clients
client.close();
}
finally {
server.close();
}

posted on 2006-11-29 13:21 linugb118 阅读(1350) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 

My Links

Blog Stats

常用链接

留言簿(1)

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜