问题
Consider the class:
class Person {
String name;
Person father;
Person mother;
List<Person> children;
}
Is there a way to indicate to jongo that father
, mother
and children
should be manual references to other objects within the same collection instead of embedded objects?
Note: this is different from DBRefs.
回答1:
Not yet.
The easiest way is to issue a second query manually.
Nevertheless, you can propably create a Jackson de/serializer to fetch documents during unmarshalling process. Few months ago, we have created a spike for fetching DBRef during unmarhsalling, this code can help : Handle DBRef during (un)marshalling
Feel free to add a feature request
回答2:
I use a way to handle it. Not sure it's perfect but it works for myself.
Let's say you have these classes
public class MyObject {
@Id
private String id;
private MyEmbeddedObject embeddedObject;
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public MyEmbeddedObject getEmbeddedObject() {
return this.embeddedObject;
}
public void setEmbeddedObject(MyEmbeddedObject embeddedObject) {
this.embeddedObject = embeddedObject;
}
}
public class MyEmbeddedObject {
@Id
private String id;
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
}
You want to store MyEmbeddedObject in collection "embed" and Object in collection "object" with a manual reference to "embed" collection ids. For example :
object : { id:1, embeddedObjectId: 99 }
embed : { id : 99 }
You can implement a custom serializer and deserializer for the MyEmbeddedObject
public class MyEmbeddedObjectSerializer extends JsonSerializer<MyEmbeddedObject> {
@Override
public void serialize(MyEmbeddedObject value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeText(value.getId());
}
}
public class MyEmbeddedObjectDeserializer extends JsonDeserializer<MyEmbeddedObject> {
@Override
public MyEmbeddedObject deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
MyEmbeddedObject obj = new MyEmbeddedObject();
obj.setId(jsonParser.getString());
return new MyEmbeddedObject();
}
}
If your register your serializer in Jongo, the problem is that it will be used for MyEmbeddedObject as a member of MyObject but also for MyEmbeddedObject when it is stored by itself in the "embed" collection.
To apply the custom serizalizers/deserializers only when MyEmbeddedObject is embed in MyOBject, I use Mixin annotations.
public interface MyObjectMixIn {
@JsonSerialize(using=MyEmbeddedObjectSerializer .class)
public MyEmbeddedObject getEmbeddedObject();
@JsonDeserialize(using=MyEmbeddedObjectDeserializer.class)
public void setEmbeddedObject(MyEmbeddedObject embeddedObject);
}
Then define a module
public class MyModule extends SimpleModule {
@Override
public void setupModule(SetupContext context) {
context.setMixInAnnotations(MyObject.class, MyObjectMixIn.class);
}
}
Finaly register the module in Jongo
Jongo jongo = new Jongo(db, JacksonMapper.Builder().registerModule(new MyModule ()).build());
Now to use it for storage in Mongo
- Store the embeddedObject by itself in collection "embed" to get an id
- Be sure the embeddedObject member of object contains the id
- Store the object in collection "object". Only the id of the embedded object will be stored
And to read datastore
- Read the object from collection "object". The embeddedobject will be initialize only with its ID
- If you need it, read the embeddedObject in collection "embed".
EDIT : to avoid lazy loading and load the complete object at deserialization, HandlerInstantiator object from Jackson is useful to customize serializer and deserializer construction mechanism.
Hope that helps.
来源:https://stackoverflow.com/questions/14939433/manual-references-support