Spring Data& mongodb转换器错误

时间:2013-12-07 03:58:42

标签: java spring mongodb spring-data spring-data-mongodb

我正在使用Spring数据连接到mongodb。请在下面查看我的问题:

现在,我有两个数据模型(用户和草稿):

@Document

public class User implements Serializable {
@Id
private String id;
private String showName;
private String password;
//..... (other attributes)

@DBRef
private List<Draft> createdDraft = new ArrayList<Draft>();

//constructors
public User() {
super();
}

public User(String id, String showName, String password, //....other attributes
List<Draft> createdDraft) {
super();
this.id = id;
this.showName = showName;
this.password = password;
//....
}

//getters and setters
}

@Document

public class Draft {
@Id
private String id;
private String title;
private Date createTime;
private Date lastEditTime;
@DBRef
private User lastEditor;
@DBRef
private User mainAuthor;
@DBRef
private List<User> coAuthors = new ArrayList<User>();
private String externalURL;

//constructors..
public Draft() {
super();
}

public Draft(String id, String title, Date createTime, Date lastEditTime,
User lastEditor, User mainAuthor, String externalURL) {
super();
this.id = id;
this.title = title;
this.createTime = createTime;
this.lastEditTime = lastEditTime;
this.lastEditor = lastEditor;
this.mainAuthor = mainAuthor;
this.externalURL = externalURL;
}

//getters and setters...

}

在我的项目中,我已成功创建用户 那么,我想向现有用户添加草稿。

public String CreateNewDraft(User mainAuthor)
{
Draft draft = new Draft();

draft.setMainAuthor(mainAuthor); 

Date now = new Date(System.currentTimeMillis());

draft.setCreateTime(now);

mainAuthor.getCreatedDraft().add(draft); 

//insert the draft --> Successful (1)

mongoOps.insert(draft);

//update the user --> Successful (2)

mongoOps.save(mainAuthor);

//find the last inserted draft. --> Errors.

Draft d = mongoOps.findOne(query(where("createTime").is(now) ), Draft.class);

return d.getId()
}

在(1)中,我找到了一个在mongoDB中创建的新“草稿”文档,它有_id =它有52a1591597d738f7b397be96。

在(2)中,我发现现有的用户(mainAuhtor)文档在createdDraft字段中添加了一个条目,如 [{“$ ref”:“draft”,“$ id”:{“$ oid”:“52a1591597d738f7b397be96”}}}

异常&amp;日志:

org.springframework.web.util.NestedServletExceptio n:处理程序处理失败;嵌套异常是java.lang.StackOverflowError

org.springframework.web.servlet.DispatcherServlet。 doDispatch(DispatcherServlet.java:972)org.springframework.web.servlet.DispatcherServlet。 doService(DispatcherServlet.java:852)org.springframework.web.servlet.FrameworkServlet.p rocessRequest(FrameworkServlet.java:882)org.springframework.web.servlet.FrameworkServlet.dOGet(FrameworkServlet.java:778)javax.servlet。 http.HttpServlet.service(HttpServlet .java:621)javax.servlet.http.HttpServlet.service(HttpServlet .java:728)org.apache.tomcat.websocket.server.WsFilter.doFilt er(WsFilter.java:51)< / p>

根本原因

java.lang.StackOverflowError

java.net.SocketInputStream.socketRead0(Native Method)java.net.SocketInputStream.read(Unknown Source)java.net.SocketInputStream.read(Unknown Source)java.io.BufferedInputStream.fill(Unknown Source)java.io .BufferedInputStream.read1(Unknown Source)java.io.BufferedInputStream.read(Unknown Source)org.bson.io.Bits.readFully(Bits.java:46)org.bson.io.Bits.readFully(Bits.java:33 )org.bson.io.Bits.readFully(Bits.java:28)com.mongodb.Response。(Response.java:40)com.mongodb.DBPort.go(DBPort.java:124)com.mongodb.DBPort。 call(DBPort.java:74)com.mongodb.DBTCPConnector.innerCall(DBTCPConnecto r.java:286)com.mongodb.DBTCPConnector.call(DBTCPConnector.jav a:257)com.mongodb.DBApiLayer $ MyCollection ._ find(DBApiLa yer.java:310)com.mongodb.DBApiLayer $ MyCollection。 _find(DBApiLa yer.java:295)com.mongodb.DBCollection.findOne(DBCollection.java:346)com.mongodb.DBCollection。 findOne(DBCollection.java:331)com.mongodb.DBRefBase.fetch(DBRefBase.java:53)org.springframework.data.mongodb.core。 convert.Mapp ingMongoConverter.readValue(MappingMongoConverter。 java:1046)org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.access $ 100(MappingMongoConverter .java:77)org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter $ MongoDbPropertyValueProvider.get PropertyValue(MappingMongoConverter。 java:999)org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.getValueInternal(MappingMongoCon verter.java:755)org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter $ 2.doWithAssociation(MappingMongo Converter.java :265)org.springframework.data.mapping.model.BasicPersis tentEntity.doWithAssociations(BasicPersistentEntit y.java:269)org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.read(MappingMongoConverter.java:262)org。 springframework.data.mongodb.core.convert.Mapp ingMongoConverter.read(MappingMongoConverter.java:223)org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.readCollectionOrArray(MappingMon goConverter.java:788)org.springframework.data .mongodb.cor e.convert.Mapp ingMongoConverter.readValue(MappingMongoConverter。 java:1048)org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.access $ 100(MappingMongoConverter .java:77)org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter $ MongoDbPropertyValueProvider.get PropertyValue(MappingMon < / p>

有人可以帮我看看吗?非常感谢!

2 个答案:

答案 0 :(得分:3)

这是spring数据mongodb的一个bug(或预期的行为?)(我在1.3.x版本中得到了这个,没试过1.4.x)。

问题是User已将Draft和Draft引用到同一用户实例,因此转换器进入无限循环。

@Document
public class User implements Serializable {
...

@DBRef
private List<Draft> createdDraft = new ArrayList<Draft>();

@Document
public class Draft {
...

@DBRef
private User lastEditor;
@DBRef
private User mainAuthor;
@DBRef
private List<User> coAuthors = new ArrayList<User>();

你应该使用简单的id引用,而不是DBRef(甚至在http://docs.mongodb.org/manual/reference/database-references/建议适用于大多数用例)

如果你发现自己经常使用DBRef,你应该考虑使用不同类型的数据库,例如:图表数据库。

答案 1 :(得分:0)

您应该从mongo数据库映射您收到的实体(文档)。

使用Springs Converter interface

例如:

public class ProfileReadConverter implements Converter<DBObject, Profile> {
@Override
public Profile convert(DBObject source) {
    @SuppressWarnings("unchecked")
    Profile p = new Profile((ObjectId) source.get("_id"), (boolean) source.get("active"), (String) source.get("name"),
            (String) source.get("shortName"), (List<Person>) source.get("person"));
    return p;
    }
}

<强> Profile.java

@Document(collection = "profile")
public class Profile {

@Id
private ObjectId id;
private boolean active;
@Indexed(unique = true)
@Field("ProfileName")
private String name;
private String shortName;
@DBRef
private List<Person> person = new ArrayList<Person>();

public Profile() {

}

@PersistenceConstructor
public Profile(ObjectId id, boolean active, String name, String shortName, List<Person> person,) {
    this.id = id;
    this.active = active;
    this.name = name;
    this.shortName = shortName;
    this.person = person;
}
//getter and setter

<强> Person.java

@Document(collection = "person")
public class Person extends Ressource {

@Indexed
private String firstname;
private String lastname;
@Field("email")
@Indexed(unique = true)
private String eMailAddress;
private String login;
@DBRef
private List<Profile> profiles = new ArrayList<Profile>();

public Person(ObjectId id, String firstname, String lastname, String eMailAddress, String login) {
    this.setId(id);
    this.firstname = firstname;
    this.lastname = lastname;
    this.eMailAddress = eMailAddress;
    this.login = login;
}

@PersistenceConstructor
public Person(ObjectId id, String firstname, String lastname, String eMailAddress, String login,
        List<Profile> profiles) {
    this.firstname = firstname;
    this.lastname = lastname;
    this.eMailAddress = eMailAddress;
    this.login = login;
    this.profiles = profiles;
}

主要或测试类

    ...
    Profile profileFind = mongoOps.findOne(new Query(where("shortName").is("SE")), Profile.class, "profile");