自定义Spring MongoRepository - 按类过滤

时间:2016-07-11 08:31:24

标签: java spring mongodb spring-data

我有几个Java文档存储在mongodb的同一个集合“app”中。我的意图是将它用于常见的持久性操作(插入,查找,删除......)。当我尝试仅为其中一个类定义存储库时出现问题,因为我定义的存储库将搜索所有实体,而我需要的是一个存储库,我可以调用所有mongorepository标准函数(find,findAll ,找到...)。我的解释很难理解,这就是我现在所拥有的:

基础文件:

@Document(collection = "app")
@NoRepositoryBean
public abstract class AbstractApplicationDocument {    
    @Id
    public String mongoId;
    // more variables, getters, setters...
}

其中一个子文档(会有很多)。

@EqualsAndHashCode(callSuper=true)
public class ClientApplicationDocument extends AbstractApplicationDocument
{
    @Id
    public String mongoId;    
}

Base Repository

@NoRepositoryBean
public interface ApplicationRepository<T, ID extends Serializable>  extends MongoRepository<T, ID>  {

}

扩展存储库(我希望按类过滤)

public interface HttpClientRepository extends ApplicationRepository<HttpClientDocument, String> {
}

如果我可以重用MongoDb实用程序,我想避免的临时解决方案示例

@Component
public class HttpClientRepositoryImpl {

    @Autowired
    private HttpClientRepository clientRepo;

    @Autowired
    private MongoTemplate mongo;

    public List<HttpClientDocument> findAll() {    
        Query query = new Query();
        query.addCriteria(Criteria.where("_class").is(HttpClientDocument.class.getName()));
        mongo.getConverter();
        return mongo.find(query, HttpClientDocument.class,"app");
    }
}

gradle中的相关信息。我添加这个是因为我看到了一些对我无效的解决方案。可能是因为他们使用不同的库:

compile("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootVersion}")
compile ("org.springframework:spring-context-support:4.1.8.RELEASE");

有没有简单的解决方案?

1 个答案:

答案 0 :(得分:2)

您可以通过多种方式自定义Spring Data存储库。您可以提供自定义存储库基类或提供custom implementation classes

特别针对您的问题,SimpleMongoRepository不会限制_class字段的查询。您可以在下面看到自定义存储库基类的示例,该基类限制findAll查询方法仅使用声明的实体类型。

您还需要将该模式应用于要限制为特定类类型的MongoRepository级别上声明的其他方法。

@EnableMongoRepositories(repositoryBaseClass = MyMongoRepository.class)
static class Config {
}

static class MyMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> {

    private final MongoEntityInformation<T, ID> metadata;
    private final MongoOperations mongoOperations;

    public MyMongoRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
        super(metadata, mongoOperations);
        this.metadata = metadata;
        this.mongoOperations = mongoOperations;
    }

    @Override
    public List<T> findAll() {

        Query query = new Query();
        query.restrict(this.metadata.getJavaType());

        return this.mongoOperations.find(query, this.metadata.getJavaType(), this.metadata.getCollectionName());
    }
}

findAll查询现在限制类类型和查询例如ModelRepository extends MongoRepository<Model, String>看起来像是:

{ "_class" : { "$in" : [ "com.example.Model"]}}

使用@Query的查询方法可以用于传递类类型(@Query("{'_class': ?0}"))但是没有办法限制派生查询方法的类类型(List<Model> findByFirstnameAndLastname(…))。

我们的Jira中有open ticket与限制存储库类型有关。该特定票证与多态查询有关,但从本质上讲,它与查询方法的类型限制有关。