Spring Data Mongo Repository:: 跨所有 Repo 问题的通用共享方法 [英] Spring Data Mongo Repository:: Common shared method across all Repo issue

查看:17
本文介绍了Spring Data Mongo Repository:: 跨所有 Repo 问题的通用共享方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用例

我正在尝试使用 Spring Data MongoDB 的 向所有存储库添加自定义行为功能.

I am trying to use Adding custom behaviour to all repositories functionality of Spring Data MongoDB.

文档无用地描述了如何使用 JPA 进行连接.无论如何,配置设置与 Mongo 等效.

The documentation unhelpfully describes how to connect using JPA. Anyways got the config setup with Mongo equivalent.

我想为所有实体添加一个 findByCategoryName(String categoryName) 方法,因为我的所有实体都将有一个 Category .Category 是一个 DBRef 对象,所以必须使用自定义查询.

I want to add a findByCategoryName(String categoryName) method to all entities as all my entities will have a Category . Category is a DBRef object so have to use custom query.

下面是配置的相关部分

<!-- Activate Spring Data MongoDB repository support -->
<mongo:repositories base-package="com.domain.*.repo" repository-impl-postfix="CustomImpl" 
    factory-class="com.domain.commonrepo.CommonMongoRepoFactoryBean"/>

<bean id="mappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />

<mongo:mapping-converter mapping-context-ref="mappingContext">
    <mongo:custom-converters base-package="com.domain.mongo.converter" />
</mongo:mapping-converter>

<bean id="entityInformationCreator" class="org.springframework.data.mongodb.repository.support.DefaultEntityInformationCreator">
    <constructor-arg name="mappingContext" ref="mappingContext" />
</bean>

..

FactoryBean

    @NoRepositoryBean
    public class CommonMongoRepoFactoryBean<T extends MongoRepository<?,?>, ID extends        
    Serializable> extends MongoRepositoryFactoryBean{

@Autowired
private static MongoTemplate mongoTemplate;

protected MongoRepositoryFactory getRepositoryFactory(Class<T> clazz) {
    return new CommonMongoRepoFactory(clazz);
}

private static class CommonMongoRepoFactory extends MongoRepositoryFactory {
    private Class clazz;

    public CommonMongoRepoFactory(Class clazz) {
        super(mongoTemplate);
        this.clazz = clazz;
    }

    public CommonMongoRepoImpl getTargetRepository() {
        return new CommonMongoRepoImpl(clazz);
    }

    public Class<?> getRepositoryClass() {
        return CommonMongoRepoImpl.class;
    }
}

我知道这有点麻烦,但没有文档就很痛苦.如果有人知道更好,请给我一个 github 链接:-)

I know it's a bit of a hack but with no documentation it is a pain. If anyone knows better PLEASE give me a github link :-)

通用 Repo 界面

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

public List<T> findByCategoryName(String categoryName);        

实施

    @NoRepositoryBean
    public class CommonMongoRepoImpl<T, ID extends Serializable> extends SimpleMongoRepository<T,    
    ID> implements CommonMongoRepo<T, ID> {

private Class<T> type;

@Autowired
private static MongoTemplate mongoOperations;

@Autowired
private static EntityInformationCreator entityInformationCreator;

@Autowired
private CategoryRepo categoryRepo;

public CommonMongoRepoImpl(Class<T> type) { 
    super((MongoEntityInformation<T, ID>) entityInformationCreator.getEntityInformation(type), mongoOperations);
}

@Override
public List<T> findByCategoryName(String categoryName) {

    Category category = categoryRepo.findByName(categoryName);

    return mongoOperations.find(query(where("categories.$id").is(category.getId())), type);
}

问题

现在当我尝试使用常用方法时,我得到一个异常

Now when I am trying to use the common method I get an exception

在实体"中找不到属性类别.我猜想当 mongo repo 试图自动实现该方法时.尽管我将 bean 声明为 @NoRepositoryBean

No Property category found in "Entity". Which is I guess when mongo repo is trying to auto implement the method. This is inspite of me declaring the bean as @NoRepositoryBean

请帮忙!!!不想为所有实体添加相同的自定义方法

PLEASE HELP!!! Dont want to add the same custom method to all the entities

推荐答案

这里是最好的解决方案!

Here is the best solution!

第一步:
为界面添加自定义方法!
增加一个自定义的方法

Step One:
Add a custom method to interface!
增加一个自定义的方法

#自定义界面

/**
 * Basic Repository for common custom methods
 * @author liangping
 */

import java.io.Serializable;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;

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

      public Page<T> search(Query query, Pageable pageable);
}

实施

第二步:
为您的自定义方法添加实现!
实现你的自定义方法

Step Two:
Add implement for your custom method!
实现你的自定义方法

/**
 * implement for wootide basic repository
 * @author liangping
 */

import java.io.Serializable;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;

public class WootideRepositoryImpl<T, ID extends Serializable> extends
        SimpleMongoRepository<T, ID> implements WootideRepositoryCustom<T, ID> {

    public WootideRepositoryImpl(MongoEntityInformation<T, ID> metadata,
            MongoOperations mongoOperations) {
        super(metadata, mongoOperations);
    }

    @Override
    public Page<T> search(Query query, Pageable pageable) {
        long total = this.getMongoOperations().count(query, this.getEntityInformation().getJavaType() );
        return new PageImpl<T>(this.getMongoOperations().find(query.with(pageable), this.getEntityInformation().getJavaType()), pageable, total);
    }

}

为自定义仓库创建新工厂

Create a new factory for custom repository

/**
 * Repository Factory for all Subrepository
 * @author liangping
 */

import java.io.Serializable;

import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;

public class WootideRepositoryFactoryBean<R extends MongoRepository<T, I>, T, I extends Serializable>
        extends MongoRepositoryFactoryBean<R, T, I> {

    @Override
    protected RepositoryFactorySupport getFactoryInstance(
            MongoOperations operations) {
        return new WootideMongoRepositoryFactory<T,I>( operations );
    }

    private static class WootideMongoRepositoryFactory<T, ID extends Serializable>
            extends MongoRepositoryFactory {

        private MongoOperations mongo;
        public WootideMongoRepositoryFactory(MongoOperations mongoOperations) {
            super(mongoOperations);
            this.mongo = mongoOperations;
        }

        @SuppressWarnings("unchecked")
        protected Object getTargetRepository(RepositoryMetadata metadata) {

            TypeInformation<T> information =  ClassTypeInformation.from((Class<T>)metadata.getDomainType());
            MongoPersistentEntity<T> pe = new BasicMongoPersistentEntity<T>(information);
            MongoEntityInformation<T,ID> mongometa = new MappingMongoEntityInformation<T, ID>(pe);

            return new WootideRepositoryImpl<T, ID>( mongometa,  mongo);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return WootideRepositoryCustom.class;
        }
    }
}

让它工作

<mongo:repositories base-package="com.***.mongodb" 
factory-class="com.***.mongodb.custom.WootideRepositoryFactoryBean"/>

祝你好运!祝你好运!

这篇关于Spring Data Mongo Repository:: 跨所有 Repo 问题的通用共享方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆