- 浏览: 634139 次
- 性别:
- 来自: 北京
博客专栏
-
实战cglib
浏览量:50665
文章分类
最新评论
-
zhongyuanceshi:
非常厉害。看了下有了整体认识
NanoHttpd源码分析 -
di1984HIT:
xuexile!!
使用Jackson在Java中处理JSON -
小胖vs小猪:
能说明一下jar包的引用情况么。
实战CGLib系列之proxy篇(一):方法拦截MethodInterceptor -
魔主万界DEV:
楼主写的不错啊!赞一个!
一个FTP Pool工具类的实现(Commons Pool) -
yuanliangding:
java里的select不是要用户自己调了?然后拿出key一个 ...
IO系列文章之五:读《Scalable io in java》看Socket网络编程模型演变
上次的Blog中写到要写一篇关于mongodb的ORM工具的文章。上个月程序基本写完,这回把Blog补上:)
本文主要介绍mongodb的ORM工具morphia的使用。
首先介绍抽象类AbstractMongoDAO,里面包含有Morphia的初始化代码,因此继承了BasicDAO。AbstractMongoDAO.java:
public class AbstractMongoDAO<T, K> extends BasicDAO<T, K> { protected static final Morphia morphia = createMorphia(); protected static final Mongo mongoInstance = createMongoInstance(); protected static final Datastore morphiaDs = createDataStore(); protected AbstractMongoDAO(Class<T> entityClass, Datastore ds) { super(entityClass, ds); } private static Morphia createMorphia() { return new Morphia(); } private static Datastore createDataStore() { morphia.mapPackage("mongodb.orm.model", true);//映射model的包路径 if (DatabaseProject.DB_CONFIG.containsKey("mongodb.username")) { return morphia.createDatastore(mongoInstance, DatabaseProject.DB_CONFIG.getString("mongodb.db") , DatabaseProject.DB_CONFIG.getString("mongodb.username"), DatabaseProject.DB_CONFIG.getString("mongodb.password").toCharArray()); } Datastore ds = morphia.createDatastore(mongoInstance, DatabaseProject.DB_CONFIG.getString("mongodb.db")); ds.ensureIndexes(); return ds; } protected AbstractMongoDAO(Class<T> entityClass, Mongo mongo, Morphia morphia, String dbName) { super(entityClass, mongo, morphia, dbName); } private static Mongo createMongoInstance() { MongoOptions mo = new MongoOptions(); mo.socketKeepAlive=true; mo.autoConnectRetry = true; mo.maxAutoConnectRetryTime=10; mo.connectionsPerHost = 40; mo.connectTimeout = 20 * 1000; mo.socketTimeout = 60 * 1000; try { if (DatabaseProject.DB_CONFIG.containsKey("mongodb.ips")) { return new Mongo(getServerAddrsFromConf("mongodb"),mo); } return new Mongo(new ServerAddress(DatabaseProject.DB_CONFIG.getString("mongodb.ip"), DatabaseProject.DB_CONFIG.getInt("mongodb.port")),mo); } catch (Throwable e) { DatabaseProject.LOGGER.error("Failed to init mongodb", e); throw new ExceptionInInitializerError(e); } } @SuppressWarnings("unchecked") public static List<ServerAddress> getServerAddrsFromConf(String confKeyPre) throws NumberFormatException, UnknownHostException { ArrayList<ServerAddress> res = new ArrayList<ServerAddress>(); List<Object> ips = DatabaseProject.DB_CONFIG.getList(confKeyPre + ".ips"); List<Object> ports = DatabaseProject.DB_CONFIG.getList(confKeyPre + ".port"); if (ports.size() < ips.size()) { int defPort = 0; if (ports.size() != 0) defPort = Integer.parseInt(ports.get(0).toString()); for (int i = 0; i < ips.size(); ++i) { if (defPort == 0) res.add(new ServerAddress(ips.get(i).toString())); else res.add(new ServerAddress(ips.get(i).toString(), defPort)); } } else { for (int i = 0; i < ips.size(); ++i) { res.add(new ServerAddress(ips.get(i).toString(), Integer.parseInt(ports.get(i).toString()))); } } return res; } public static Mongo getMongoInstance() { return mongoInstance; } public static DB getDB() { return morphiaDs.getDB(); } public static Morphia getMorphia() { return morphia; } public Iterable<Key<T>> insert(Iterable<T> entries, WriteConcern wc) { return ds.insert(entries, wc); } public Iterable<Key<T>> insert(Iterable<T> entries) { return ds.insert(entries); }
}
注意createMongoInstance方法(上一篇介绍mongo java driver的文章中也有提到),主要是实例化一个mongo实例。
接下来是createDataStore方法,该方法通过morphia对象及使用mongo实例创建一个Datastore对象。其中morphia.mapPackage("mongodb.orm.model", true);是将mongodb.orm.model包路径下的所有类都进行关系对象映射。
下面是Model类:
/** * @Entity * value代表生成的集合名称、不写默认为类名(此处设置为与类名相同) * noClassnameStored如果设置为false,文档中会生成一列className保存类名("className":"mongodb.orm.model.OrmColl") */ @Entity(value="OrmColl",noClassnameStored = true) /** * @Indexes * 创建复合索引(用,分隔). * 此处设置userId升序,name降序. * unique:设置为唯一,无法插入重复值. * dropDups:当为某个字段创建唯一索引时,删除其他相同值的记录。只保留第一条记录. * true-删除重复,false-不删除重复(当有重复值时唯一索引创建失败),默认为false. * @Indexes({@Index(...),@Index(...)})多个索引加{}并用,分隔. * Datastore的ensureIndexes调用时才会创建索引. */ @Indexes(@Index(value="userId,-name",unique=true,dropDups=false)) public class OrmColl{ @Id private ObjectId id;//Id private long userId; private String name; private int age; private Date createDate = new Date(); @Property("male")//该属性存储到collection中元素名指定为male private boolean sex; /** * concreteClass:为接口指名实现类,默认 * java.util.ArrayList for List * java.util.HashSet for Set * java.util.HashMap for Map * 此处为List指明实现类为java.util.Vector */ @Property(concreteClass=java.util.Vector.class) public List<String> list;//添加范型指名list类型,否则出现警告 @Embedded(value="embedded_doc") private InnerDocument doc;//嵌入文档,默认为属性名.此处指定了元素名称. @Transient private int transientValue;//设置为@Transient不会被持久化 @Serialized private int serializedValue;//序列化 @Version Long version;//乐观锁 @Reference private RefOrmColl refOrmColl;//自动生成名为refOrmColl的内嵌文档,包含"$ref"和"$id"属性,指明引用集合名及@Id属性值. @Reference private List<RefOrmColl> refList;//自动生成名为refList的数组,数组的每个元素都是内嵌文档,文档形式同refOrmColl. public OrmColl(){} @PrePersist private void prePersist() {createDate = new Date();} //setter & getter }
补充@Entity(concern = "SAFE")属性(粘贴自文档):
NONE: No exceptions are raised, even for network issues
NORMAL: Exceptions are raised for network issues, but not server errors
SAFE: Exceptions are raised for network issues, and server errors; waits on a server for the write operation
FSYNC_SAFE: Exceptions are raised for network issues, and server errors and the write operation waits for the server to flush the data to disk
REPLICAS_SAFE: Exceptions are raised for network issues, and server errors; waits for at least 2 servers for the write operation
其中version属性不需要getter和setter方法,内嵌对象为InnerDocument。代码如下:
/** * 被@Embedded注解的类不允许有@Id */ @Embedded public class InnerDocument { private String type; private long longValue; private Date createDate; public InnerDocument(){} @PrePersist private void prePersist() {createDate = new Date();} //setter & getter... }
引用对象为RefOrmColl.java,格式如下:
@Entity(value="RefOrmColl",noClassnameStored = true) public class RefOrmColl { @Id private ObjectId id;//被关联的集合一定要包含@Id属性 private long longValue; private String type; private Date date; @PrePersist private void prePersist() {date = new Date();} //setter&getter... }
在OrmColl的集合中自动生成RefOrmColl类型对象属性名的内嵌文档或数组(本例中是refOrmColl和refList),包含"$ref"和"$id"属性,以指明引用集合名及@Id属性值.
DAO实现类:
OrmCollDao.java如下:
public class OrmCollDao extends AbstractMongoDAO<OrmColl,ObjectId>{//OrmColl主键是OjectId private static OrmCollDao childDaoInstance = createDAOInstance(); protected static DefaultMorphiaMongoDAO<RefOrmColl> refDao = DefaultMorphiaMongoDAO.getInstance(RefOrmColl.class); private static OrmCollDao createDAOInstance(){ return new OrmCollDao(OrmColl.class,morphiaDs); } protected OrmCollDao(Class<OrmColl> entityClass,Datastore ds){ super(entityClass,ds); } protected OrmCollDao(Class<OrmColl> entityClass, Mongo mongo, Morphia morphia, String dbName){ super(entityClass,mongo,morphia,dbName); } public static OrmCollDao getInstance(){ return childDaoInstance; } /** * 数据初始化 */ public static void insertRefOrmColl(){ List list = new ArrayList(); for(int i=0;i<100;i++){ RefOrmColl roc = new RefOrmColl(); roc.setLongValue(i); roc.setType("type"+i); list.add(roc); } //insert可以批量插入list,save只能单个插入,但save可以更新. refDao.insert(list); } /** * 数据初始化 */ public static void insertOrmColl(){ //List<OrmColl> ormList = new ArrayList<OrmColl>(); //查询一个关联集合的List Query<RefOrmColl> listQuery = refDao.createQuery().field("longValue").lessThan(10); List<RefOrmColl> refList = refDao.find(listQuery).asList(); for(int i=0;i<100;i++){ OrmColl oc = new OrmColl(); oc.setAge(1+i); oc.setName("name"+i); oc.setUserId(10000+i); oc.setSex(true); oc.setTransientValue(12345); oc.setSerializedValue(1234567); InnerDocument doc = new InnerDocument();//内嵌文档 doc.setType("type_str"); doc.setLongValue(1986L); oc.setDoc(doc); Query<RefOrmColl> query = refDao.createQuery().field("longValue").equal(i); RefOrmColl refColl = refDao.findOne(query);//查询关联集合的文档 if(refColl!=null){ //设置关联 oc.setRefOrmColl(refColl); oc.setRefList(refList); } OrmCollDao.getInstance().save(oc);//使用save方法会自动生成@version属性 //ormList.add(oc); } //OrmCollDao.getInstance().insert(ormList);//使用批量插入,文档中不会自动生成@version属性. } /** * 根据id加载对象 */ public static void get(String _id){ OrmCollDao dao = OrmCollDao.getInstance(); OrmColl obj = dao.get(new ObjectId(_id)); displayObj(obj); } /** * filter查询方式(直接使用 > < >= <= = exists等表达式) */ public static void findByFilter(){ OrmCollDao dao = OrmCollDao.getInstance(); //filter之间以and连接 Query query = dao.createQuery().filter("age >",1); query.filter("userId <=", 10010); query.filter("male =", true); query.filter("embedded_doc.type =", "type_str"); query.filter("refList exists ", true); List<OrmColl> list = dao.find(query).asList(); System.out.println("list.size:"+list.size()); for(int i=0;i<list.size();i++){ displayObj(list.get(i)); } } /** * Fluent查询方式(使用morphia封装的方法greaterThan、lessThanOrEq、equal、exists) */ public static void findByFluent(){ OrmCollDao dao = OrmCollDao.getInstance(); Query query = dao.createQuery(); //不同条件之间为and query.field("age").greaterThan(1); query.field("userId").lessThanOrEq(10010); query.field("male").equal(true); query.field("embedded_doc.type").equal("type_str"); query.field("refList").exists();//doesNotExist List<OrmColl> list = dao.find(query).asList(); System.out.println("list.size:"+list.size()); for(int i=0;i<list.size();i++){ displayObj(list.get(i)); } } /** * Fluent查询方式(根据id查询文档) */ public static void findById(String _id){ OrmCollDao dao = OrmCollDao.getInstance(); Query query = dao.createQuery(); query.field(Mapper.ID_KEY).equal(new ObjectId(_id));//Mapper.ID_KEY == "_id" OrmColl obj = dao.findOne(query); displayObj(obj); } /** * Fluent查询方式 ,OR条件查询 */ public static void orQuery(){ OrmCollDao dao = OrmCollDao.getInstance(); Query<OrmColl> query = dao.createQuery(); query.or( query.criteria("userId").equal(10010), query.criteria("age").greaterThan(1) ); List<OrmColl> list = dao.find(query).asList(); System.out.println("list.size:"+list.size()); for(int i=0;i<list.size();i++){ displayObj(list.get(i)); } } /** * Count求和 */ public static void getCount(){ OrmCollDao dao = OrmCollDao.getInstance(); Query query = dao.createQuery().field("userId").greaterThanOrEq(10095); long count = dao.count(query); System.out.println(count); } /** * 更新操作 */ public static void updateEntity(String _id){ OrmCollDao dao = OrmCollDao.getInstance(); UpdateOperations<OrmColl> ops = dao.createUpdateOperations().set("createDate",new Date()).set("serializedValue",12345); UpdateResults<OrmColl> ur = dao.update(dao.createQuery().field(Mapper.ID_KEY).equal(new ObjectId(_id)),ops); System.out.println(ur.getInsertedCount()); } /** * 对象转换并打印对象属性 */ public static void displayObj(OrmColl obj){ Morphia morphia = getMorphia(); DBObject object = morphia.toDBObject(obj);//将对象转换成DBObject. System.out.println(object.toString()); } /** * Mapper and EntityCache */ public static void mapper(String _id){ OrmCollDao dao = OrmCollDao.getInstance(); OrmColl oc = dao.get(new ObjectId(_id)); Mapper mapper = morphia.getMapper(); if(mapper!=null && morphia.isMapped(OrmColl.class)){ System.out.println("getCollectionName:"+mapper.getCollectionName(oc)); System.out.println("Id:"+mapper.getId(oc)); System.out.println("Key:"+mapper.getKey(oc)); System.out.println("keyToRef:"+mapper.keyToRef(mapper.getKey(oc))); System.out.println("Options:"+mapper.getOptions()); } EntityCache cache = mapper.createEntityCache(); cache.putEntity(mapper.getKey(oc),oc); System.out.println("cache obj 1: "+cache.getEntity(mapper.getKey(oc)).getName()); System.out.println("cache obj 2: "+cache.getEntity(mapper.getKey(oc)).getName()); System.out.println("cache obj exists: "+cache.exists(mapper.getKey(oc))); EntityCacheStatistics ecs = cache.stats(); System.out.println("EntityCacheStatistics1: "+ecs.toString());//cache统计1: 1 entities,3 hits cache.putProxy(mapper.getKey(oc),oc); System.out.println("cache proxy: "+cache.getProxy(mapper.getKey(oc)).getName()); ecs = cache.stats(); System.out.println("EntityCacheStatistics2: "+ecs.toString());//cache统计2: 2 entities,4 hits //所有已经映射的class for (MappedClass mc : mapper.getMappedClasses()) { System.out.println("getMappedClasses: " + mc); } for (EntityInterceptor ei : mapper.getInterceptors()) { System.out.println("EntityInterceptor: " + ei); } } }
以上是针对OrmColl的集合建立的DAO,由于使用了泛型,因此find、update等操作都针对OrmColl,所以如果你需要在DAO中同时对其它集合进行操作的话,可以使用以下通用的DAO,DefaultMorphiaMongoDAO.java:
public class DefaultMorphiaMongoDAO<T> extends AbstractMongoDAO<T, ObjectId> { private static final Map<String,DefaultMorphiaMongoDAO> _instanceMap = new ConcurrentHashMap<String,DefaultMorphiaMongoDAO>(); protected DefaultMorphiaMongoDAO(Class<T> entityClass, Datastore ds) { super(entityClass,ds); this.ensureIndexes(); } public static DB getDB(){ return morphiaDs.getDB(); } public static <T> DefaultMorphiaMongoDAO<T> getInstance(Class<T> clazz){ DefaultMorphiaMongoDAO inst = _instanceMap.get(clazz.getSimpleName()); if (inst==null) { inst = new DefaultMorphiaMongoDAO<T>(clazz,morphiaDs); _instanceMap.put(clazz.getSimpleName(),inst); } return inst; } }
通过泛型,你就可以用该DAO对任何Collection进行操作了,(注意,此处代码,<T, ObjectId>可以支持不同的Key类型,不一定是ObjectId)。
至此,Morphia的学习算是告一段落了。
其实在遇到很多问题的时候要多看文档,下面列出一些Morphia的参考资料,希望对读者有所帮助:
1.morphia官方用户手册: http://code.google.com/p/morphia/wiki/GettingStarted
2.morphia在线API文档地址:http://morphia.googlecode.com/svn/site/morphia/apidocs/index.html
评论
代码里的这个是啥对象方法呀?或者是哪个包提供的呀,我的morphia里没有的哇
在我blog里面搜索DatabaseProject即可找到。
代码里的这个是啥对象方法呀?或者是哪个包提供的呀,我的morphia里没有的哇
发表评论
-
关于Redis扩容方案
2013-08-08 07:33 2965首先关于Redis,目前某应用redis部署2台机器,做m ... -
Redis回顾与总结(持续更新中)
2013-02-01 22:20 3716前一段时间公司某项目使用了Redis作为缓存服务器,年前不 ... -
MongoDB Sharding深入学习
2012-09-04 21:59 6082对于MongoDB的Sharding(分片)技术并不陌生,但是 ... -
MongoDB程序开发之使用Java驱动
2012-06-24 11:21 9623在工作中使用到了MongoDB,平时也看了一些资料,感觉Mon ... -
公司某产品MongoDB分布式架构总结
2012-05-01 19:21 4408本篇博客的内容是对目前公司某产品在mongodb架构方面的一些 ... -
MongoDB在Linux环境下安装
2012-04-26 00:04 11231.到MongoDB官网下载linux安装文件(步骤省略)。 ... -
MongoDB在windows环境下安装
2012-04-21 00:07 11251.到mongodb官网下载一个win32版本(步骤此处略过, ... -
MongoDB之旅
2012-04-20 22:11 8477MongoDB是目前工作中经常使用到的NoSQL数据库。 本 ...
相关推荐
在本文中,我们将探讨MongoDB的ORM框架Morphia,并结合Spring Data MongoDB的使用来创建一个集成应用。ORM(对象关系映射)框架是将数据库操作转化为对象模型的方法,简化了开发过程,使得开发者可以专注于业务逻辑...
Morphia 是一个 Java ORM(对象关系映射)库,用于简化 MongoDB 的数据操作,将数据模型与数据库文档之间的转换自动化。在本文中,我们将深入探讨如何使用 Morphia 进行 MongoDB 的操作。 首先,为了在 Java 项目中...
**Morphia:一个NoSQL的...总之,Morphia是连接Java应用程序与MongoDB的强大桥梁,它的使用使得开发过程更加高效和便捷。通过深入学习和实践,开发者可以充分利用MongoDB的灵活性和高性能,同时享受到ORM带来的便利。
Morphia 是一个针对 MongoDB 的 Java ORM(对象关系映射)框架,它允许开发者使用 Java 对象直接操作 MongoDB 数据库,简化了数据库操作。以下是对 Morphia 操作 MongoDB 的详细介绍: 1. **安装与配置** - **...
Morphia-0.99.jar则是一个较旧版本的Morphia库,它是针对MongoDB的Java ORM(对象关系映射)工具。Morphia允许Java开发者将对象模型直接映射到MongoDB的数据结构,简化了数据操作。通过Morphia,开发者可以避免编写...
总的来说,Morphia提供了一个强大的工具集,使得Java开发者能够更高效地与MongoDB数据库交互,简化了数据库操作的复杂性,提高了开发效率。通过注解和Fluent API,Morphia使得MongoDB的数据操作变得直观且易于维护。
在IT行业中,Spring框架是Java开发者的首选工具之一,它为构建企业级应用程序提供了全面的解决方案。MongoDB则是一款流行的NoSQL数据库系统,适合处理大量非结构化数据。Morphia是Google开发的一个用于Java的MongoDB...
首先,为了连接到MongoDB,你需要在项目中引入MongoDB的Java驱动程序和相关的ORM(对象关系映射)库。Morphia是一个常见的选择,它是Google开发的一个用于MongoDB的数据映射框架,简化了在Java应用中操作MongoDB的...
此外,还有ORM(Object-Relational Mapping)库,如Morphia和Spring Data MongoDB,它们帮助简化数据对象与数据库文档之间的转换,提高开发效率。 7. **MJORM**:Mongo-Java-ORM(MJORM)是一个专门为MongoDB设计的...
本文将详细介绍如何在 Spring 4.2 中集成 MongoDB 框架,特别是使用 Morphia 1.1 这个 ORM(对象关系映射)工具进行数据操作。 ### 1. 安装与配置 首先,确保已安装 MongoDB 服务器并运行。然后,在项目中添加以下...
Morphia是Google开发的一个流行的MongoDB ORM框架,它提供了丰富的API和功能。GlacialMapper借鉴了Morphia的一些设计理念,如注解驱动的对象映射,但可能在某些方面进行了优化或创新,以满足特定需求或性能要求。 ...
Morphia一个nosql的ORM框架 对此二次封装
虽然Apache Commons BeanUtils库提供了一种便捷的方式进行转换,但在大规模应用中,考虑使用ORM框架如Morphia或Spring Data MongoDB,它们提供了更高级别的抽象和自动转换功能,可以简化对象与数据库之间的交互。...
HtmlUnit网页分析工具包,模拟浏览器运行 PhantomJS JavaScriptEngine MongoDB ORM框架 Morphia JUC:Java线程池、线程协作、线程安全类 日志log4j 1.7.25 Java反射 单例模式、工厂模式、代理模式 项目结构 biz包:...
如果项目选择使用MongoDB作为数据库,此手册会介绍如何集成MongoDB驱动,进行文档操作,以及使用ODM(对象数据映射)库如Morphia。 10. **Play开发Tip总结**: 最后,这份文档可能是开发者经验的汇集,包含了开发...
8. **使用 Morphia**:Morphia 是一个 ORM 库,它可以将 Kotlin 类映射到 MongoDB 文档。通过 Morphia,你可以更直观地操作数据库,例如,通过 `@Entity` 注解定义数据模型,然后使用 `Datastore` 对象进行持久化...