morphia进阶
注解原始和级别类型的属性
保存原始和基本类型的属性到Mongo中,你不必为他们添加任何注解:
... private int myInt; private Date myDate; private List<String> myStrings; private String[] stringArray;
默认情况下,Morphia将会试着映射所有支持的基本和原始类型到Mongo,包括这些类型的数组。
MongoDB仅仅有一下数据类型:
- Integer(32位有符号值)
- Long(64有符号值)
- Double(64位IEEE745浮点值)
- String (字符串)
这里有些有价值的转换:
- float → double
- byte → int
- short → int
- char → String
并且,依赖于你的模型中存在的类型和数据库将会试着自动为你转换。我的意思是,因为在MongoDB数据库中只存在三种数字类型(32/64有符号, 64位FP)这将相当
容易转换。下面的列表为当前什么样的基本和原始类型可以被保存:
- enum(在Mongo中作为String保存)
- java.util.Date(在Mongo中保存为从新纪元UTC的毫秒数)
- java.util.Locale(作为字符串保存)
- com.mongodb.DBRef
- com.mongodb.ObjectId
正如我我们上面的例子所示,Morphia还支持java.util.List, java.util.Set和java.util.Map容器, 和任何支持的原始类型的数组。
如果你想把一个属性排除映射到Mongo中, 你可以使用@Transient注解
import com.google.code.morphia.annotations.Transient; ... @Transient private int myTransientInt;
默认情况下,Morphia把属性名作为Mongo中的字段名。这个可以通过@Property注解进行修改,指定一个名称。
import com.google.code.morphia.annotations.Property; ... @Property("my_integer") private int myInt; //在MongoDB中为my_integer
User Collections(使用容器)
Morphia 支持容器(List, Set, Map) 和数组(Integer)
private Set<String> tags; private Map<String,Translation> translations; @Reference private List<Article> relatedArticles;
Morphia 将使用一下实现(默认)来创建容器:
- java.util.ArrayList for List
- java.util.HashSet for Set
- java.util.hashMap for Map
如果你想使用其他的实现, 你可以在注解中重写他们
@Property(concreteClass = java.util.TreeSet.class) private Set<String> tags; @Embedded(concreteClass = java.util.TreeMap.class) private Map<String,Translation> translations; @Reference(concreteClass = java.util.Vector.class) private List<Article> relatedArticles;
映射对象
Create a Morphia instance(创建一个Morphia实例)
首先你要做的就是创建一个Morphia实例,并且告诉他你要映射的类。建议你仅创建一次Morphia实例,重复使用。映射的任何一个类都将会进行验证,如果由于某些原因你映射的类不合法将会抛出一个MappingException异常
import com.google.code.morphia.Morphia; ... Morphia morphia = new Morphia(); morphia.map(BlogEntry.class) .map(Author.class); ...
指定Morphia去扫描一个包,映射包中的所有类。
morphia.mapPackage("my.package.with.only.mongo.entities");
Mapping a java for Persistence
保存一个实例对象到Mongo数据库中的一个容器中。调用Morphia中的toDBObject()方法,把java对象传入。
我们可以把返回的DBObject对象直接保存到Mongo中。
// map the blog entry to a Mongo DBObject DBObject blogEntryDbObj = morphia.toDBObject(blogEntry); // and then save that DBObject in a Mongo collection db.getCollection("BlogEntries").save(blogEntryDbObj);
Retrieving a java from MongoDB(从Mongo中回复一个Java对象)
从Mongo数据库中的一个文档创建一个Java对象。调用Morphia中的fromDBObject()方法即可,传入要返回的DBObject对象。
// load the DBObject from a Mongo collection BasicDBObject blogEntryDbObj = (BasicDBObject) db.getCollection("BlogEntries") .findOne(new BasicDBObject("_id", new ObjectId(blogEntryId)); // and then map it to our BlogEntry object BlogEntry blogEntry = morphia.fromDBObject(BlogEntry.class, blogEntryDbObj);
使用Morphia管理Mongdo中的Java对象的非常清楚的方法是使用DAO 支持。DAO包含了操作Mongo和Morphia的抽象方法,所以业务逻辑不用依赖Morphia。
接口使用
当我们从mongodb恢复一个对象时,如果它是一个接口,我们怎么知道它由哪个实现类实现的呢?
Morphia通过在Mongo的文档中保存一个叫“className”的属性,这个属性值对应的是java对象的一个类全名。我们必须将接口的所有实现类全部映射到Morphia实例中。
Morphia morphia = new Morphia(); morphia.map(Circle.class) .map(Rectangle.class) .map(ShapeShifter.class);
容器可以保存为一个嵌套集合:
ublic class ShapeContainer { @Embedded private List<Shape> shapes; ... }
或者保存为一个应用集合:
public class ShapeContainer { @Reference private List<Shape> shapes; ... }
使用DAO
DAO封装了存储和调用的代码,控制类只要注入一个DAO对象,使用它就不需要关心数据持久化和恢复了。
Morphia基于DAO接口提供了BasicDAO实现类,它使用Datastore对象来存储和查询POJO对象,可以通过BasicDAO的方法来create/update, read, and delete 对象,可以参考它提供的例子和模式。
意味着你的DAO类只要继承BasicDAO,只需要写一个普通的查询方法,就能查询你自己的对象。
public class BlogEntryDAO extends BasicDAO<BlogEntry, ObjectId> { public BlogEntryDAO( Morphia morphia, Mongo mongo ) { super(mongo, morphia, "myBlogDb"); } }