简体   繁体   English

Spring Data Mongodb - 用于收集不同类型的存储库

[英]Spring Data Mongodb - repository for collection with different types

I have a mongo collection that may contain three types of entities that I map to java types: 我有一个mongo集合,可能包含三种类型的实体,我映射到java类型:

  • Node 节点
  • LeafType1 LeafType1
  • LeafType2 LeafType2

Collection is ment to store tree-like structure using dbRefs of child nodes in parent entry. 集合是使用父条目中的子节点的dbRefs来存储树状结构。

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? 我没有在Spring参考文档中找到任何关于主题的信息,所以我在这里问:有没有办法使用Repository机制来处理可能包含不同类型对象的集合?

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> { }

If Node\\LeafType1\\LeafType2 are sub-classes of AbstractMyCollectionNode, then things will be easy. 如果Node \\ LeafType1 \\ LeafType2是AbstractMyCollectionNode的子类,那么事情就很容易了。 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. Spring Data会将名为'_class'的属性添加到mongodb集合中的文档中,以便它可以指出要实例化的类。

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. 并且 ,如果mongodb集合中的文档没有“_class”属性。 You can use Converter : 你可以使用Converter

When storing and querying your objects it is convenient to have a MongoConverter instance handle the mapping of all Java types to DBObjects. 在存储和查询对象时,让MongoConverter实例处理所有Java类型到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. 但是,有时您可能希望`MongoConverter完成大部分工作,但允许您有选择地处理特定类型的转换或优化性能。

Spring data uses the Repository-Declarations as entry-point when looking for Entity classes (it does not scan packages for entities directly). Spring数据在查找实体类时使用Repository-Declarations作为入口点(它不直接扫描实体的包)。

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: 因此,您需要做的就是为您的子类声明一个“未使用的”存储库接口,就像您在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 . 您不必使用其他LeafTypeX存储库,您可以坚持使用NodeRepository存储和查找LeafType1LeafType2类型的对象。 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. 但是需要声明其他两个存储库,以便在初始扫描发生时将LeafType1LeafType2作为实体找到。

PS: This all assumes, of course, that you have @Document(collection= "nodes") annotations on your LeafType1 and LeafType2 classes PS:当然,这一切都假定您的LeafType1LeafType2类上有@Document(collection= "nodes")注释

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM