Spring Data Mongo Repository:: 跨所有 Repo 问题的通用共享方法 [英] Spring Data Mongo Repository:: Common shared method across all Repo issue
问题描述
用例
我正在尝试使用 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屋!