I have a mongo collection that may contain three types of entities that I map to java types:
Collection is ment to store tree-like structure using dbRefs of child nodes in parent entry.
I didn't find any information about subject in Spring reference documentation so I'm asking here: Is there a way to use Repository
mechanism to work with collection that may contain different types of objects?
Declaring several repositories for different types in one collection seems like not very good idea because I always struggle with situations when queried object is not of expected type and creating one repository for abstract class that all possible types inherrit doesn't seems to work.
To illustrate what I mean:
/**
* This seems not safe
*/
public interface NodeRepository extends MongoRepository<Node, String> { }
public interface LeafType1Repository extends MongoRepository<LeafType1, String> { }
public interface LeafType2Repository extends MongoRepository<LeafType2, String> { }
/**
* This doesn't work at all
*/
public interface MyCollectionRepository extends MongoRepository<AbstractMyCollectionNode, String> { }
MongoTemplate provides a simple way for you to save, update, and delete your domain objects and map those objects to documents stored in MongoDB. You can save, update and delete the object as shown below. MongoOperations is the interface that MongoTemplate implements.
For performing MongoDB Join two collections, you must use the $lookup operator. It is defined as a stage that executes a left outer join with another collection and aids in filtering data from joined documents. For example, if a user requires all grades from all students, then the below query can be written: Students.
Yes, DataNucleus JPA allows it, as well as to many other databases. You make compromises by using the JPA API for other types of datastores, but it makes it easy to investigate them.
MongoTemplate — MongoTemplate implements a set of ready-to-use APIs. A good choice for operations like update, aggregations, and others, MongoTemplate offers finer control over custom queries. MongoRepository — MongoRepository is used for basic queries that involve all or many fields of the document.
If Node\LeafType1\LeafType2 are sub-classes of AbstractMyCollectionNode, then things will be easy. Just declare the repository like you write:
public interface MyCollectionRepository extends MongoRepository<AbstractMyCollectionNode, String> { }
We have done this in a project, and it works good. Spring Data will add an property named '_class' to the documents in mongodb collection, so that it can finger out which class to instantiate.
Documents that stored in one collection may have some similarity, maybe you can extract a generic class for them.
Here are some code copied from one of our projects:
Entity:
public abstract class Document {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
....
public class WebClipDocument extends Document {
private String digest;
...
Repository:
public interface DocumentDao extends MongoRepository<Document, String>{
...
And, if your documents in mongodb collection does not have the "_class" property. You can use Converter:
When storing and querying your objects it is convenient to have a MongoConverter instance handle the mapping of all Java types to DBObjects. However, sometimes you may want the `MongoConverter’s do most of the work but allow you to selectively handle the conversion for a particular type or to optimize performance.
Spring data uses the Repository-Declarations as entry-point when looking for Entity classes (it does not scan packages for entities directly).
So all you need to do is to declare an "unused" Repository-Interface for your sub-classes, just like you proposed as "unsafe" in your OP:
public interface NodeRepository extends MongoRepository<Node, String> {
// all of your repo methods go here
Node findById(String id);
Node findFirst100ByNodeType(String nodeType);
... etc.
}
public interface LeafType1Repository extends MongoRepository<LeafType1, String> {
// leave empty
}
public interface LeafType2Repository extends MongoRepository<LeafType2, String> {
// leave empty
}
You do not have to use the additional LeafTypeX
repositories, you can stick with the NodeRepository
for storing and looking up objects of type LeafType1
and LeafType2
. But the declaration of the other two repositories is needed, so that LeafType1
and LeafType2
will be found as Entities when initial scanning takes place.
PS: This all assumes, of course, that you have @Document(collection= "nodes")
annotations on your LeafType1
and LeafType2
classes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With