使用Morphia检索引用的文档会返回奇怪的错误

时间:2014-01-28 23:49:36

标签: java mongodb morphia

我一直在玩Morphia,因为我在使用Spring Data for Mongodb处理引用文档时遇到了问题。下面是我拥有的数据和代码的快照......

以下是我的用户和组类(省略了getter和setter)

用户类

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import org.mongodb.morphia.annotations.Reference;



@Entity(value="users")
public class User {

@Id
    private String id;
private String username;
private String firstname;
private String lastname;
private String email;
private long cellnumber;
private Date datejoined;
private boolean active;
private Account account;

@Reference(value="usergroups", lazy=true)
private List<Group> usergroups = new ArrayList<>();

}

小组课。

@Entity(value="groups")
public class Group {
@Id
private String id;
private String name;
private String description;
private long creationdate;

@Reference
private User user;

}

我现在正在运行以下方法,在main方法中命名为scenario1()和scenario2()。

    private void scenario1() {

    User newUser = setupUser(new User());
    datastore.save(newUser);
    Query<User> query = datastore.createQuery(User.class)
            .field("firstname").equal("Jome");
    User user = query.get();

    Account account = new Account();
    account.setBalance(0.0);
    account.setSmsvalue(0.18);

    UpdateOperations<User> update = datastore
            .createUpdateOperations(User.class);
    update.set("account", account);

    user.setAccount(account);
    datastore.save(user);
    List<Group> groups = query.get().getUsergroups();

    Group group1 = new Group();
    group1.setCreationdate(new Date().getTime());
    group1.setDescription("test group for first user");
    group1.setName("Group One");
    group1.setUser(query.get());
    datastore.save(group1);
    groups.add(group1);
    update.add("usergroups", group1);
    datastore.update(query, update);

    Group group2 = new Group();
    group2.setCreationdate(new Date().getTime());
    group2.setDescription("Another test group for first user");
    group2.setName("Group Two");
    group2.setUser(query.get());
    datastore.save(group2);
    groups.add(group2);

    update.add("usergroups", group2);

    datastore.update(query, update);

    System.out.println(user);
    List<Group> savedgroups = user.getUsergroups();
    System.out.println(savedgroups);
}

这是输出

User [id=52e8894ef148a7f866b9f1ac, username=jomski2013, firstname=Jome, lastname=Akpoduado, email=jomea@yookos.com, cellnumber=123456789]
[Group [id=52e8894ef148a7f866b9f1ad, name=Group One, description=test group for first user, creationdate=1390971214880, owner=User [id=52e8894ef148a7f866b9f1ac, username=jomski2013, firstname=Jome, lastname=Akpoduado, email=jomea@example.com, cellnumber=123456789]], Group [id=52e8894ef148a7f866b9f1ae, name=Group Two, description=Another test group for first user, creationdate=1390971214884, owner=User [id=52e8894ef148a7f866b9f1ac, username=jomski2013, firstname=Jome, lastname=Akpoduado, email=jomea@example.com, cellnumber=123456789]]]

和mongo控制台的视图

> db.users.find().pretty()
{
"_id" : ObjectId("52e8894ef148a7f866b9f1ac"),
"account" : {
    "balance" : 0,
    "smsvalue" : 0.18
},
"active" : true,
"cellnumber" : NumberLong("123456789"),
"className" : "org.imanmobile.sms.core.domain.User",
"datejoined" : ISODate("2014-01-29T04:53:34.746Z"),
"email" : "jomea@example.com",
"firstname" : "Jome",
"lastname" : "Akpoduado",
"password" : "$2a$10$c0SAy7eJZv06eqmAWQNUP.YrXtB7tDOdi11lkZqlAVgzVGU9RCbCS",
"usergroups" : [
    DBRef("groups", "52e8894ef148a7f866b9f1ad"),
    DBRef("groups", "52e8894ef148a7f866b9f1ae")
],
"username" : "jomski2013"
}

> db.groups.find().pretty()
{
"_id" : ObjectId("52e8894ef148a7f866b9f1ad"),
"className" : "org.imanmobile.sms.core.domain.Group",
"name" : "Group One",
"description" : "test group for first user",
"creationdate" : NumberLong("1390971214880"),
"user" : DBRef("users", "52e8894ef148a7f866b9f1ac")
}
{
"_id" : ObjectId("52e8894ef148a7f866b9f1ae"),
"className" : "org.imanmobile.sms.core.domain.Group",
"name" : "Group Two",
"description" : "Another test group for first user",
"creationdate" : NumberLong("1390971214884"),
"user" : DBRef("users", "52e8894ef148a7f866b9f1ac")
}

然而,当我随后运行下面的scenario2()

    private void scenario2() {
    Query<User> query = datastore.createQuery(User.class);

    User user = query.field("username").equal("jomski2013").get();
    System.out.println("Number of groups: " + user.getUsergroups().size());
}

我收到了错误......

Caused by: org.mongodb.morphia.mapping.MappingException: The reference({ "$ref" : "groups", "$id" : "52e8894ef148a7f866b9f1ad" }) could not be fetched for org.imanmobile.sms.core.domain.User.usergroups
at org.mongodb.morphia.mapping.ReferenceMapper.resolveObject(ReferenceMapper.java:304)
at org.mongodb.morphia.mapping.ReferenceMapper$1.eval(ReferenceMapper.java:243)
at org.mongodb.morphia.utils.IterHelper.loopOrSingle(IterHelper.java:89)
at org.mongodb.morphia.mapping.ReferenceMapper.readCollection(ReferenceMapper.java:239)
at org.mongodb.morphia.mapping.ReferenceMapper.fromDBObject(ReferenceMapper.java:163)
at org.mongodb.morphia.mapping.Mapper.readMappedField(Mapper.java:602)
at org.mongodb.morphia.mapping.Mapper.fromDb(Mapper.java:584)
at org.mongodb.morphia.mapping.Mapper.fromDBObject(Mapper.java:294)
at org.mongodb.morphia.query.MorphiaIterator.convertItem(MorphiaIterator.java:71)
at org.mongodb.morphia.query.MorphiaIterator.processItem(MorphiaIterator.java:58)
at org.mongodb.morphia.query.MorphiaIterator.next(MorphiaIterator.java:53)
at org.mongodb.morphia.query.QueryImpl.get(QueryImpl.java:408)
at org.imanmobile.sms.PlayClass.scenario2(PlayClass.java:35)
at org.imanmobile.sms.PlayClass.run(PlayClass.java:29)
at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:644)

我的问题是为什么Morphia能够获取第一次保存而不是随后保存的组?有什么不同或者我应该注意或缺少什么?

1 个答案:

答案 0 :(得分:1)

用户组DBRef数组与这些引用的文档之间存在类型不匹配:

"usergroups" : [
    DBRef("groups", "52e82c05f148a7310a899a50"),
    DBRef("groups", "52e82c05f148a7310a899a4f")
]

$ref.id的类型为字符串

而群组集合中的_id类型为 ObjectId

"_id" : ObjectId("52e82c05f148a7310a899a4f")

"_id" : ObjectId("52e82c05f148a7310a899a50")

这就是无法获取引用的原因。

您不必运行辅助查询,这是由Morphia自动完成的。

很难确定造成这种不匹配的原因。可能是最初在你的Java Group课程中 private String ObjectId;字段,已用于插入,后来又更改为private String id;

在任何情况下要解决此问题,您必须使用$ref.idusergroups数组包含在ObjectId数组中以解决此问题:

"usergroups" : [
     DBRef("groups", ObjectId("52e82c05f148a7310a899a50")),
     DBRef("groups", ObjectId("52e82c05f148a7310a899a4f"))
]

您还必须相应地更改Group映射(将id属性设置为ObjectId

如果您想保留原样(将所有内容视为字符串),只需删除数据库(我猜您只是在尝试),然后从新鲜开始