今天研究了一下MongoDB的應用,用到了這個Morphia的開源框架,使用起來很方便,能實現java類和數據庫collections之間的相互映射。下面是在網上找來的Morphia文章與大家進行分享。

這里也有篇文章很好的講解了使用 Morphia 和MongoDB 实现域模型持久性的問題

地址:http://www.ibm.com/developerworks/cn/java/j-morphia/index.html

1. 什么是Morphia

Morphia是一个开放源代码的对象关系映射框架,它对MongoDB数据库 java版驱动进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵MongoDB数据库,也让Java程序员可以从复杂数据库设计中脱离出来,从而将更多的精力投入到业务逻辑中去。Morphia是一个轻量级的类型安全的Java对象to/from MongoDB 库,具有以下特征:

  • 它易于使用,而且非常轻巧 ,每种类型使用一次反射。
  • 数据存储(DataStore) 和 DAO<T,V> 访问抽象,或自己实现...
  • 使用运行时验证的类型安全 (Type-safe)和 Fluent 查询(Query) 支持
  • 基于注解的行为映射,无XML文件
  • 扩展 : Validation(jsr303) ,以及SLF4J日志
  • 生命周期方法/事件(Lifecycle Method/Event) 支持
  • 可与Guice、Spring和其它DI框架很好整合或协作
  • 很多扩展点(新的注解,转换器,行为映射,日志等)
  • 不存储Null/Empty值(默认)
  • GWT支持(实体仅为POJO) - (GWT忽略注释)
  • 允许原始类型、void toObject(DBObject) 或 DBObject  fromObject(Object) fromObject的高级映射器

2. Morphia开发环境配置

首先,从http://code.google.com/p/morphia/downloads/list下载Morphia开发包,最新版为morphia-0.99.jar,然后从http://www.mongodb.org/downloads下载MongoDB数据库 java版驱动最新版为mongo-2.7.2.jar,直接将这两个jar包include到项目中即可,当然在程序的运行前应保证MongoDB数据库后台服务进程已经启动。(MongoDB数据库的具体安装使用请参考其它相关资料),要求使用JavaSE 5或更高版本。

注:morphia在googleCode上代碼只更新到了0.98版本,我用是在GitHub上的,版本是已經更新到了1.2.2。里面修改和增加了許多新功能。我是用Maven來進行jar管理,具體 訪問http://search.maven.org/網站,查找morphia(com.github.jmkgreen.morphia)即可。已經不是goolge的包了。

3. Morphia 中Java 注释使用

      Morphia使用Java注释的特性来描述Java对象如何被持久化到MongoDB数据库中去。以下是Morphia比较常用的注释。

l  @Id

@Id 注释指示Morphia哪个字段用作文档 ID。如果试图持久保存对象(其 @Id 注释的字段为 null),则Morphia会自动生成 ID值。

l  @Entity

@Entity 注释是必需的。其声明了在专用MongoDB集合上该类作为文档将持久保存。在默认情况下,Morphia使用类名称来命名集合。

l  @Embedded

@Embedded 注释说明Morphia将此对象实例嵌入到另一个对象中去。而不单独的放到一个MongoDB集合。

l  @Reference

 @Reference 注释说明对象是对另外一个集合中的文档的引用。在从 MongoDB集合中加载对象时,Morphia遵循着这些引用来建立对象关系。

l  @Indexed

类属性标记@Indexed注释,表明为此属性增加索引。

l  @Property

类属性标记@ Property注释,表明为此属性在MongoDB数据库取一个别名。

l  @Transient

类属性标记@Transient注释则表明这个字段将不被持久化到数据库。

4. Morphia编程模型

本节上通过定义一个简单的类以及一些操作代码片段来说明Morphia功能的编程模型,使得我们可以从总体上了解Morphia开发。

1.   定义被持久类

@Entity

classMyEntity {

@Id

ObjectIdid;

Stringname;

}

2.   初始化morphia

Mongomongo= new Mongo("localhost");//连接到本地mongoDB数据库

Morphiamorphia= new Morphia();

morphia.mapPackage("MyEntity");//告诉Morphia映射哪些类

Datastoreds= morphia.createDatastore(mongo ,"myDB");//创建名为“myDB”数据库,mongo最好使用单实例模式

ds.ensureIndexes();//在标记为@Id的类属性上创建索引

ds.ensureCaps();//设置默认的mongoDB集合容量

3.   保存被持久化类

MyEntitye= ...;

ds.save(e);//将MyEntity对象持久化到mongoDB数据库中

4.   查询

MyEntitye=ds.find(MyEntity.class).get();//通过类型取的第一个数据项

MyEntitye= ds.find(MyEntity.class).field("name")

.equal("someName").get();

5. Datasotre接口

Datastore接口把Java对象保存到MongoDB或从MongoDB中访问Java对象提供了安全类型的方法。它提供了get/find/save/delete方法为你操作Java对象。

5.1  Get方法

                  Get方法返回一个实体对象通过@Id。get方法只是find(...)方法的一个精简版,通过ID访问。它会返回一个实体对象,或者null如果没有找到的话。

Datastoreds = ...Hotel hotel = ds.get(Hotel.class, hotelId);

5.2  Find方法

                 find方法只是对Query的一个轻量级的封装。作为封装它将返回一个Query,它实现Iterable<T>和QueryResults接口。

//在循环中使用

for(Hotelhotel: ds.find(Hotel.class, "stars >", 3))

  print(hotel);

//作为一个List返回

List<Hotel>hotels= ds.find(Hotel.class, "stars >", 3).asList();

//对结果排序

List<Hotel>hotels= ds.find(Hotel.class, "stars>",3).sort("-stars").asList();

//返回第一个符合条件的结果

HotelgsHotel =ds.find(Hotel.class, "name", "GrandSierra").get();

这里是有效的操作符列表["=","==", "!=", "<>",">","<", ">=", "<=","in","nin", "all", "size","exists"]。如果没有指定操作符默认使用"=", 就像上面的例子,"="和“==”是等价的表示相等,"!="和"<>"是等价的表示不相等。

5.3   Save方法

 大部分对MongoDB数据库操作的工作及Morphia映射解析工作已由Morphia完成。本方法直截了当,只要我们在定义持久化类时使用好Morphia注释即可。

Hotelhotel = new Hotel();

ds.save(hotel);

//@Id 属性如果没有指定的话,将被自动生成,

ObjectIdid = hotel.getId();

5.4

它已很好的自我解释,delete方法将从MongoDB数据库删除数据项,基于一个查询如id或其它条件。

Datastoreds = ...

//通过指定主键Id,删除数据项

ds.delete(Hotel.class,"Grand Sierra Resort");

//基于一个查询,删除数据项

ds.delete(ds.createQuery(Hotel.class).filter("pendingDelete",true));

在morphia支持mongoDB以原子方式做一些操作的功能。如删除一个实体,并且同时返回要删除的项。FindAndDelete方法首先查询要删除的项,并且删除。

5.5 Update方法

Updates应用在服务器上并且允许复杂但非常有效的修改。 假设要跟踪一个用户的最近网站登录信息。在任何成功登录网站的用户都修改时间,但是将不必加载此用户的信息然后在重新保存整个对象信息。而是相反地,你可以局部的修改并且执行一个有效的修改。

@Entity

class User

{

   @Id private ObjectId id;

   private long lastLogin;

   //... 其它属性

   private Query<User>queryToFindMe() {

return datastore.createQuery(User.class)

.field(Mapper.ID_KEY).equal(id);

   }

   public void loggedIn(){

      long now=System.currentTimeMillis();

     UpdateOperations<User> ops  = datastore.

createUpdateOperations(User.class).set("lastLogin",now);

     ds.update(queryToFindMe(), ops);

      lastLogin = now;

   }

}

6. 代碼分享

我寫了個例子,放在googleCode上,可以查看到源代碼,地址如下:

Use this command to anonymously check out the latest projectsource code:

svn checkout http://gavin-hellomongodb.googlecode.com/svn/trunk/gavin-hellomongodb-read-only