如何解决这个Morphia映射问题??? --->警告[org.mongodb.morphia.mapping.DefaultCreator] - 在dbObj中未找到的类:

时间:2015-01-14 09:23:32

标签: java mongodb morphia

所以这就是导致问题的问题......

我使用MongoDB数据库在jBoss上运行这个javaEE应用程序。我使用Morphia与mongo进行通信......应用程序具有以下基本程序组件;

@EntityListeners(RootEntityListener.class)
public class RootEntity {
    @Id
    protected ObjectId id;
    @Indexed
    protected Long uid;
    @Indexed
    protected boolean active;
    ...
}

@Entity
public class User extends RootEntity {
    ...
}

@Entity
public class News extends RootEntity {
    ...
}

然后我的Morphia配置如下所示;

//Morphia Setup
morphia = new Morphia();
morphia.map(User.class).map(News.class);
...

然后我通过调用下面显示的方法进行查询;

public List<News> findByUID(Long uId){
    Query<News> query = getNewsQuery().field("active").equal(true).field("uid").equal(uId);
    return query.asList();
}

精细!到目前为止......没有错误。但是每个模型(用户和新闻)都会收到一个奇怪的警告。请参阅下面的StackTrace:

WARNING [org.mongodb.morphia.mapping.DefaultCreator] (http-localhost-127.0.0.1-8080-3) Class not found defined in dbObj: : 
java.lang.ClassNotFoundException: com.package.models.News from [Module "deployment.Wealth.war:main" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120)
at java.lang.Class.forName0(Native Method) [rt.jar:1.7.0_45]
at java.lang.Class.forName(Unknown Source) [rt.jar:1.7.0_45]
at org.mongodb.morphia.mapping.DefaultCreator.getClass(DefaultCreator.java:89) [morphia-0.109.jar:]
at org.mongodb.morphia.mapping.DefaultCreator.createInstance(DefaultCreator.java:37) [morphia-0.109.jar:]
at org.mongodb.morphia.mapping.Mapper.fromDBObject(Mapper.java:298) [morphia-0.109.jar:]
at org.mongodb.morphia.query.MorphiaIterator.convertItem(MorphiaIterator.java:79) [morphia-0.109.jar:]
at org.mongodb.morphia.query.MorphiaIterator.processItem(MorphiaIterator.java:65) [morphia-0.109.jar:]
at org.mongodb.morphia.query.MorphiaIterator.next(MorphiaIterator.java:60) [morphia-0.109.jar:]
at org.mongodb.morphia.query.QueryImpl.asList(QueryImpl.java:312) [morphia-0.109.jar:]
at ng.wealth.business.NewsBean.findByActive(NewsBean.java:99) [classes:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [rt.jar:1.7.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [rt.jar:1.7.0_45]
at java.lang.reflect.Method.invoke(Unknown Source) [rt.jar:1.7.0_45]
...(*the rest omitted for brevity*)...

现在,我发现这可能与Morphia的类映射有关...... org.mongodb.morphia.mapping.DefaultCreator未加载实体类(UserNews)。

经过大量研究......并参考了https://code.google.com/p/morphia/issues/detail?id=208中找到的解决方案(他们说它有效),我通过将以下内容添加到我的morphia配置中来覆盖org.mongodb.morphia.mapping.DefaultCreator;

morphia.getMapper().getOptions().objectFactory = new DefaultCreator() {
    @Override
    protected ClassLoader getClassLoaderForClass() {
        return RootEntity.class.getClassLoader();
    }
};

注意:在原始解决方案中,覆盖方法为getClassLoaderForClass(String clazz, DBObject object)但在我的情况下(由于我的Morphia版本 - 0.109 - 我认为可能是最近获得的来自mongo官方网站),方法是getClassLoaderForClass()。所以,我相应地通过返回我的RootEntity类加载器来覆盖它。

但警告仍在继续。它不一定会破坏代码,因为类(UserNews)实际上已加载,我仍然可以正常从它们获取值。但是我的日志充满了这些警告,也许我不仅仅知道应用程序的某些部分仍然对这些奇怪的警告行为不端。

所以我需要的是对这个问题的永久解决方案......以及为什么答案实际上解决问题的具体解释。谢谢你们!

3 个答案:

答案 0 :(得分:1)

Play 2.4应用程序遇到了同样的问题。对我来说,这很有效:

// Overwrite objectFactorys ClassLoader Method to use Plays ClassLoader
// This prevents the log from beeing spammed with Warning-Messages about ClassNotFoundExceptions happening in Morphias objectFactory
morphia.getMapper().getOptions().setObjectFactory(new DefaultCreator() {
    @Override
    protected ClassLoader getClassLoaderForClass() {
        if(Play.maybeApplication().isDefined()) {
            return Play.classloader(Play.maybeApplication().get());
        } else {
            return PersistedObject.class.getClassLoader();
        }
    }
});

我不太了解JavaEE,但他们也需要考虑their own class loading paradigms。希望它有所帮助。

答案 1 :(得分:0)

我认为@Id注释是必需的。最简单的方法是使用@Id protected ObjectId id添加它。或者您确保uid是唯一的,然后您可以使用@Id protected Long uid(已编入索引,因此不需要@Indexed。)

PS:不确定索引布尔值是否值得,因为基数太低了。无论如何,对于您的查询,您还需要一个复合索引。

答案 2 :(得分:0)

我今天早上才看到这篇文章(来自你的其他帖子)所以首先,我为那个道歉。 (mongodb-users列表对我来说有更多的可见性,但是我确实试着在这里监视并做出响应。)我刚刚在Morphia的master分支上运行了测试用例并且没有出现任何奇怪的错误。 (master只是1.0.1之后的一些提交。)如果你不太愿意转向纯粹的驱动程序解决方案,我建议1.0.1并制作确保迁移是必要的。