morphia是mongodb for java基础上的一个开源项目,但2011年之后几乎不在更新,非常不活跃,建议后来者谨慎选择。由于团队在比较早之前就选择了morphia,因此在未重构之前,还是尽可能的用好morphia。
morphia项目地址:
https://code.google.com/p/morphia/
这里只说morphia Reference使用的问题和使用建议
一、慎用Reference,合理使用lazy=true
@Reference有lazy属性,默认为false,当为false时,会自动加载关联的数据,跟hibernate类似。理论上Reference会引发死循环,最简单的业务模式,就是好友业务,用户A通过Reference加载关联的好友B,B通过Reference加载关联的好友A,就形成了死循环。因此在确定类似这样的业务或者业务复杂到开发人员不能掌控时,非常有必要把lazy=true。如果形成死循环,会造成链接池耗尽,请求被阻塞,占用较多的cpu,整个应用变的极慢。因此强列建议慎用@Reference,如果要用,一定要搞清楚业务,在没必要实时加载引用数据的情况下,务必加上lazy=true。
二、第三方依赖
@Reference(lazy=true)
设置lazy=true后,会发现需要cglib及proxytoys第三方包的支持,需要加入对应的jar包。
三、多个mongodb数据库,且采用spring配置时引出的Reference bug及解决办法
如果mongodb两个database,spring配置片段如下:
<bean id="mongouri" class="com.mongodb.MongoURI"> <constructor-arg value="${mongo.url}"/> </bean> <bean id="mongo" class="com.mongodb.Mongo"> <constructor-arg><ref bean="mongouri"></ref></constructor-arg> </bean> <bean id="morphia" class="com.google.code.morphia.Morphia"> <property name="mongo" ref="mongo"/> <property name="databaseName" value="cmac"/> <property name="user" value="${mongo.username}"/> <property name="password" value="${mongo.password}"/> </bean> <bean id="practisemorphia" class="com.google.code.morphia.Morphia"> <property name="mongo" ref="mongo"/> <property name="databaseName" value="practise"/> <property name="user" value="${mongo.username}"/> <property name="password" value="${mongo.password}"/> </bean> <bean id="datastore" factory-bean="morphia" factory-method="getDatastore"/> <bean id="practiseds" factory-bean="practisemorphia" factory-method="getDatastore"/>
我们为两个database分别写了两个BaseDao,让两个BaseDao分别持有不同的DatastoreImpl,没有问题,但是在使用Reference且lazy=true时,问题来了。如上的配置,spring初始化时先初始化datastore,再初始化practiseds,应用起来后,发现practiseds相关的@Reference(lazy=true)操作都正常,而datastore相关的@Reference(lazy=true)不正常,报的错误是MappingException。通过查看源码,发现getDatastore调用DatastoreHolder时是静态且单例的模式,因此当初始化practiseds时,就把之前的DatastoreHolder的静态变量覆盖了。Reference在lazy=true的情况下,会从DatastoreHolder里取当前的DatatoreImpl,而此时取到的都只是practiseds的DatatoreImpl,因此datastore相关的@Reference(lazy=true)通通抛出MappingException异常。
此问题的修复,只要在Dao对应方法里,加上以下代码:
DatastoreHolder.getInstance().set(super.getDs());
//在BaseDao里定义DatastoreImpl成员变量并注入@Resource(name = "datastore")
public DatastoreImpl getDs() { return ds; } @Resource(name = "datastore") public void setDs(DatastoreImpl ds) { this.ds = (DatastoreImpl)ds; initType(((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0])); ensureIndexes(); }
为了书写更加美观和便利,可以改造成AOP的方式
SupportReference.java
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface SupportReference {}
AbstractMorphiaReferenceAspect.aj
public abstract aspect AbstractMorphiaReferenceAspect { public AbstractMorphiaReferenceAspect() { } @SuppressAjWarnings("adviceDidNotMatch") Object around(Object model) : supportReferenceMethodExecution(model) { @SuppressWarnings("rawtypes") Class clazz = model.getClass().getSuperclass(); try{ @SuppressWarnings("unchecked") Method ds = clazz.getDeclaredMethod("getDs"); DatastoreImpl datastoreimpl =(DatastoreImpl)ds.invoke(model); DatastoreHolder.getInstance().set(datastoreimpl); }catch(Exception ex){ex.printStackTrace();} Object result = proceed(model); return result; } protected abstract pointcut supportReferenceMethodExecution(Object model); }
MorphiaReferenceAspect.aj
public aspect MorphiaReferenceAspect extends AbstractMorphiaReferenceAspect { public MorphiaReferenceAspect() { super(); } protected pointcut supportReferenceMethodExecution(Object model) : (execution(* com.hx.corebiz.*.dao.impl.*.*(..))) && @annotation(SupportReference) && this(model); }
aop.xml
<?xml version="1.0" encoding="UTF-8" ?> <aspectj> <aspects> <aspect name="com.hx.corebase.aop.morphiareference.MorphiaReferenceAspect" /> </aspects> <weaver options="-verbose"> <include within="com.hx.corebiz.*.dao.impl.*" /> </weaver> </aspectj>
在Dao类里,在需要使用@Reference(lazy=true)方法的加上Annotation @SupportReference即可
四、ignoreMisssing
ignoreMisssing会捕获Reference所有异常,如果不想看到一些烦人的异常,并让程序继续运行,ignoreMisssing=true是有必要的。比方说我们Reference到另一张表,某天另一张表的数据删除了,而开发人员也没有做关联数据的清理,此时如果ignoreMisssing=false(默认),就会抛出异常,这种情况下有必要指定ignoreMisssing=true。
五、Memcached与Reference
存入Memcached时,会对对象进行序列化,此时应注意以下三点:
1、如果你不想序列化对象里某成员,请使用transient关键字,这样可减小对象大小,节省内存空间,提高性能。
2、如果lazy=false,在序列化存入到memcache时,会加载出所有Reference对象。如果Reference是个大List<Object>,可以想像此java对象将会非常庞大。而memcache更适合小对象的缓存,默认在1M之内。不过这个策略跟总大小也有关系,本人设置memcached内存总大小为64M,放入一个大对象,报错信息page超过1M,但把总大小置成512M后,与之前一样没有设置PAGE大小(即参数-L),这时就不报错了,没有仔细研究memcache代码,但据此可判断此1M的限制,跟总大小有某种逻辑关系。当然如果光光为了消除1M限制的错误,可以通过设置-L,比如设置成5M,但这不是理想的解决办法。通过测试,memcached对一个大对象和一个小对象的存取,速度不在一个数量级上,因此如果真的有对象超过1M,最好对程序进行优化设计。像上述的情况Reference是个大List<Object>,此时把lazy=true,是非常有必要的。可大大减小对象的大小。
3、另外重复第一点,在互相引用的时候,此时如不加lazy=true,就会产生死循环,因此这种情况下lazy=true是必须的。
相关推荐
本文将深入探讨如何使用Morphia框架来操作MongoDB。 首先,你需要在项目中添加Morphia和MongoDB驱动的依赖。如果你使用的是Maven,可以在pom.xml文件中加入以下依赖: ```xml <groupId>org.mongodb.morphia ...
在这个教程中,开发者可以学习到如何在Morphia的数据实体类中使用`@Reference`注解。这个注解的目的是将一个对象的ID存储为另一个对象的属性,从而建立了一种引用关系,而不是直接保存整个对象。这样做的好处包括...
在使用Morphia框架时,经常会遇到需要更新具有`@Reference`注解的集合字段的情况。例如,在更新`UserGroup`中的成员列表时可能会遇到问题。 ##### 1.1 User类定义 ```java @Entity("User") public class User { @...
在这个压缩文件中,我们有两个重要的jar包:mongo-2.7.3.jar和morphia-0.99.jar,它们都是针对Morphia框架使用的。 MongoDB的Java驱动程序,即mongo-2.7.3.jar,是连接Java应用程序与MongoDB服务器的关键组件。它...
本篇文章将详细介绍如何使用 Morphia 和 MongoDB 来实现域模型的持久化。 首先,我们需要理解 Morphia 的基本概念。Morphia 将 Java 对象映射到 MongoDB 的文档结构,这包括实体类、数据存储、数据映射和查询API。...
morphia-0.99.jar 最新版本。
在本文中,我们将探讨MongoDB的ORM框架Morphia,并结合Spring Data MongoDB的使用来创建一个集成应用。ORM(对象关系映射)框架是将数据库操作转化为对象模型的方法,简化了开发过程,使得开发者可以专注于业务逻辑...
使用Morphia时,首先需要配置MongoDB的连接信息,然后定义实体类,这些类通常会继承自Morphia提供的`@Entity`注解的类。接着,可以使用Morphia的`Datastore`接口来执行数据库操作,如保存、查询、更新或删除数据。...
通过使用Morphia,开发者可以避免直接处理JSON格式的文档,而是专注于处理Java对象。这使得代码更易于理解和维护。 **二、Morphia的核心概念** 1. **实体(Entities)**:在Morphia中,Java类被视为实体,每个实体...
Morphia 是一个针对 MongoDB 的 Java ORM(对象关系映射)框架,它允许开发者使用 Java 对象直接操作 MongoDB 数据库,简化了数据库操作。以下是对 Morphia 操作 MongoDB 的详细介绍: 1. **安装与配置** - **...
Spring MVC、Morphia 和 MongoDB 是三个在Java开发中常用于构建Web...通过深入研究这个例子,你将能理解如何在实际项目中结合使用Spring MVC、Morphia和MongoDB,从而更好地掌握Java Web开发中的非关系型数据库集成。
morphia基于mongodb的基本开发
morphia-1.3.2.jar
在NoSQL的世界里,Morphia扮演着连接应用程序和非关系型数据库的角色,提供了类型安全和易于使用的API。 **一、MongoDB与Morphia** MongoDB是一个流行的文档型数据库,以其灵活性、高性能和横向扩展能力而受到青睐...
- **@Reference**:表示对象是另一个集合文档的引用,Morphia会处理引用关系。 - **@Indexed**:用于为属性创建索引。 - **@Property**:为属性指定MongoDB中的别名。 - **@Transient**:标记字段不应被持久化到...
要在Java项目中使用Morphia,首先需要下载MongoDB的Java驱动包,可以从GitHub官方仓库下载最新版本。同时,还需要下载Morphia的jar包,通常可以在Google Code仓库中找到。将这两个jar包导入到你的Java项目中,确保...
在本文中,我们将深入探讨如何使用 Morphia 进行 MongoDB 的操作。 首先,为了在 Java 项目中使用 Morphia,我们需要下载并引入相关的依赖库。这包括 MongoDB 的 Java 驱动包和 Morphia 的 JAR 文件。可以从官方...
morphia mongo db OR-mapping mongo db再带的CRUD 太麻烦了, 一个不错的框架 类似 Hibernate
"Morphia-example-1:Java中使用Morphia ODM和Spring的示例项目" 是一个基于Java开发的项目,其主要目的是展示如何在Java应用程序中使用Morphia对象数据映射(ODM)库来操作MongoDB数据库,并结合Spring框架进行集成...