如何正确配置 SimpleMongoRepository?
How to configure SimpleMongoRepository correctly?
我最近在用MongoDB工作,遇到了这样的问题。我需要配置SimpleMongoRepository,我找到了这个主题作为例子(使用最后一个post作为例子)Spring Data Mongo Repository:: Common shared method across all Repo issue
配置:
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(MultipleMongoProperties.class)
@EnableMongoRepositories(basePackages = "productcatalog.repository")
public class MultipleMongoConfig {
private final MultipleMongoProperties mongoProperties;
@Bean(name = "mongoTemplate")
public MongoTemplate mongoTemplate() {
return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()));
}
@Primary
@Bean(name = "primaryMongoTemplate")
public MongoTemplate primaryMongoTemplate() {
return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()));
}
@Bean(name = "secondaryMongoTemplate")
public MongoTemplate secondaryMongoTemplate() {
return new MongoTemplate(secondaryFactory(this.mongoProperties.getSecondary()));
}
@Bean("primary")
public SimpleMongoRepository<ProductModel, String> getPrimaryProductRepository() {
TypeInformation<ProductModel> typeInformation = ClassTypeInformation.from(ProductModel.class);
MongoPersistentEntity<ProductModel> mongoPersistentEntity = new BasicMongoPersistentEntity<>(typeInformation);
return new SimpleMongoRepository<>(entityInformationFor(mongoPersistentEntity, String.class), primaryMongoTemplate());
}
@Bean("secondary")
public SimpleMongoRepository<ProductModel, String> getSecondaryProductRepository() {
TypeInformation<ProductModel> typeInformation = ClassTypeInformation.from(ProductModel.class);
MongoPersistentEntity<ProductModel> mongoPersistentEntity = new BasicMongoPersistentEntity<>(typeInformation);
return new SimpleMongoRepository<>(entityInformationFor(mongoPersistentEntity, String.class), secondaryMongoTemplate());
}
@Bean("productRepository")
public MongoRepository<ProductModel, String> getRepository() {
return new MongoRepositoryImpl<>(getPrimaryProductRepository(), getSecondaryProductRepository());
}
@Bean
@Primary
public MongoDbFactory primaryFactory(final MongoProperties mongo) {
return getMongoDbFactory(mongo);
}
@Bean
public MongoDbFactory secondaryFactory(final MongoProperties mongo) {
return getMongoDbFactory(mongo);
}
public <T, ID extends Serializable> MongoEntityInformation<T, ID> entityInformationFor(MongoPersistentEntity<T> entity,
Class<ID> idType) {
return new MappingMongoEntityInformation<>(entity, idType);
}
private SimpleMongoDbFactory getMongoDbFactory(MongoProperties mongo) {
MongoCredential mongoCredential = MongoCredential.createCredential(mongo.getUsername(), mongo.getAuthenticationDatabase(), mongo.getPassword());
List<MongoCredential> mongoCredentialList = Collections.singletonList(mongoCredential);
ServerAddress serverAddress = new ServerAddress(mongo.getHost(), mongo.getPort());
MongoClient mongoClient = new MongoClient(serverAddress, mongoCredentialList);
return new SimpleMongoDbFactory(mongoClient,
mongo.getDatabase());
}
}
我的模特:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "products")
public class ProductModel {
@Id
private String id;
@Field(value = "name")
private String name;
}
但是我的 SimpleMongoRepository 配置中有一个问题,在这一行
MongoPersistentEntity<ProductModel> mongoPersistentEntity = new BasicMongoPersistentEntity<>(typeInformation);
idProperty 配置为 null,然后在使用它的后续方法中我得到 NPE。如何解决这个问题?
java.lang.NullPointerException: null
at org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation.getIdAttribute(MappingMongoEntityInformation.java:101) ~[spring-data-mongodb-1.10.9.RELEASE.jar:na]
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.findAll(SimpleMongoRepository.java:211) ~[spring-data-mongodb-1.10.9.RELEASE.jar:na]
at productcatalog.repository.MongoRepositoryImpl.findAll(MongoRepositoryImpl.java:97) ~[classes/:na]
at productcatalog.service.impl.ProductServiceImpl.getProductsByIds(ProductServiceImpl.java:36) ~[classes/:na]
at productcatalog.controller.ProductCatalogController.getProductsByIds(ProductCatalogController.java:90) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:8.5.23]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:8.5.23]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
我得到了存储库:
public class MongoRepositoryImpl<T, K extends Serializable> implements MongoRepository<T, K> {
private SimpleMongoRepository<T, K> primaryRepository;
private SimpleMongoRepository<T, K> secondaryRepository;
private SimpleMongoRepository<T, K> actualSource;
private ReadWriteLock lock = new ReentrantReadWriteLock();
private Lock writeLock = lock.writeLock();
private Lock readLock = lock.readLock();
private static final Integer DEFAULT_SIZE = 10;
public MongoRepositoryImpl(SimpleMongoRepository<T, K> primaryRepository, SimpleMongoRepository<T, K> secondaryRepository) {
this.primaryRepository = primaryRepository;
this.secondaryRepository = secondaryRepository;
actualSource = primaryRepository;
}
@Override
public T findOne(K id) {
T findResult;
try {
readLock.lock();
findResult = actualSource.findOne(id);
} finally {
readLock.unlock();
}
return findResult;
}
@Override
public List<T> findAll() {
List<T> result;
try {
readLock.lock();
result = actualSource.findAll();
} finally {
readLock.unlock();
}
return result;
}
@Override
public Iterable<T> findAll(Iterable<K> ids) {
Iterable<T> result;
try {
readLock.lock();
result = actualSource.findAll(ids);
} finally {
readLock.unlock();
}
return result;
}
除了 findAll (Iterable ids) 之外的所有方法都有效,当我使用这个方法时,我得到了 NPE 因为 idProperty = null;我该如何解决这个问题?
我遇到了同样的挑战,不幸的是找不到一个像样的例子来说明如何做到这一点。
正如您从堆栈跟踪中看到的那样,SimpleMongoRepository
在内部保持 MongoEntityInformation
,并且在 3 种情况下它明确搜索 Id 属性:findAllById()
、existsById()
deleteById()
最终调用 entityInformation.getIdAttribute()
。因此,您必须确保它熟悉您的实体及其 Id 属性。
你是这样操作的:
@Bean("primary")
public SimpleMongoRepository<ProductModel, String> getPrimaryProductRepository() {
TypeInformation<ProductModel> typeInformation = ClassTypeInformation.from(ProductModel.class);
BasicMongoPersistentEntity<ProductModel> mongoPersistentEntity = new BasicMongoPersistentEntity<ProductModel>(typeInformation);
//add Id-property, o/w SimpleMongoRepository asks (e.g. delete()) getIdQuery(id) and we fail on `entityInformation.getIdAttribute()`
Class<ProductModel> aClass = ProductModel.class;
Field field = null;
try
{
field = aClass.getDeclaredField("id");
}
catch (NoSuchFieldException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Property property = Property.of(ClassTypeInformation.from(ProductModel.class), field);
MongoPersistentProperty idProperty = new BasicMongoPersistentProperty(property , mongoPersistentEntity, SimpleTypeHolder.DEFAULT, null);
mongoPersistentEntity.addPersistentProperty(idProperty);
MongoEntityInformation<ProductModel, String> mongoEntityInformation = new MappingMongoEntityInformation<ProductModel, String>(mongoPersistentEntity);
return new SimpleMongoRepository<>(mongoEntityInformation, primaryMongoTemplate());
}
...与 'secondary' 相同。
希望对您有所帮助。
我认为您需要 org.springframework.data.mongodb.repository.support.MongoRepositoryFactory
.
的专用实例
在您的配置中设置工厂 class:
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(MultipleMongoProperties.class)
@EnableMongoRepositories(basePackages = "productcatalog.repository", repositoryFactoryBeanClass = MultipleMongoRepositoryFactoryBean.class)
public class MultipleMongoConfig {
/* ...code... */
}
然后,在您的 MultipleMongoRepositoryFactoryBean
:
public class MultipleMongoRepositoryFactoryBean<R extends MongoRepository<T, I>, T, I extends Serializable> extends MongoRepositoryFactoryBean<R, T, I> {
protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
return new MultipleMongoRepositoryFactory<T, I>(operations);
}
}
然后根据元数据在 MongoRepositoryFactory
中创建自己的一组存储库。
public class MultipleMongoRepositoryFactory<T, ID extends Serializable> extends MongoRepositoryFactory {
private final MongoOperations mongoOperations;
public MultipleMongoRepositoryFactory(MongoOperations mongoOperations) {
super(mongoOperations);
}
@Override
protected Object getTargetRepository(RepositoryMetadata metadata) {
/* Add personalyzed stuff here */
return super.getTargetRepository(metadata);
}
}
请注意 MongoRepositoryFactory::getEntityInformation(EntityMetadata)
有一个方法 returns MongoEntityInformation
,它实际上是从您的配置中抛出异常。因此,如果你真的需要手动配置你的存储库,你可以尝试注入 MongoRepositoryFactory
.
请注意,仅当您需要在存储库实现上实现特定内容时才需要这样做。如果您只使用 Spring 数据提供的默认接口,则不需要像这样。
编辑: 您可以查看 Spring Data 的文档以获取更多信息。 https://docs.spring.io/spring-data/mongodb/docs/1.6.4.RELEASE/reference/html/#repositories.custom-implementations. This was retrieved from version 1.6.4, which is the one I experienced the same problem as yourself. For the current release, please refer to https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.custom-implementations.
我最近在用MongoDB工作,遇到了这样的问题。我需要配置SimpleMongoRepository,我找到了这个主题作为例子(使用最后一个post作为例子)Spring Data Mongo Repository:: Common shared method across all Repo issue
配置:
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(MultipleMongoProperties.class)
@EnableMongoRepositories(basePackages = "productcatalog.repository")
public class MultipleMongoConfig {
private final MultipleMongoProperties mongoProperties;
@Bean(name = "mongoTemplate")
public MongoTemplate mongoTemplate() {
return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()));
}
@Primary
@Bean(name = "primaryMongoTemplate")
public MongoTemplate primaryMongoTemplate() {
return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary()));
}
@Bean(name = "secondaryMongoTemplate")
public MongoTemplate secondaryMongoTemplate() {
return new MongoTemplate(secondaryFactory(this.mongoProperties.getSecondary()));
}
@Bean("primary")
public SimpleMongoRepository<ProductModel, String> getPrimaryProductRepository() {
TypeInformation<ProductModel> typeInformation = ClassTypeInformation.from(ProductModel.class);
MongoPersistentEntity<ProductModel> mongoPersistentEntity = new BasicMongoPersistentEntity<>(typeInformation);
return new SimpleMongoRepository<>(entityInformationFor(mongoPersistentEntity, String.class), primaryMongoTemplate());
}
@Bean("secondary")
public SimpleMongoRepository<ProductModel, String> getSecondaryProductRepository() {
TypeInformation<ProductModel> typeInformation = ClassTypeInformation.from(ProductModel.class);
MongoPersistentEntity<ProductModel> mongoPersistentEntity = new BasicMongoPersistentEntity<>(typeInformation);
return new SimpleMongoRepository<>(entityInformationFor(mongoPersistentEntity, String.class), secondaryMongoTemplate());
}
@Bean("productRepository")
public MongoRepository<ProductModel, String> getRepository() {
return new MongoRepositoryImpl<>(getPrimaryProductRepository(), getSecondaryProductRepository());
}
@Bean
@Primary
public MongoDbFactory primaryFactory(final MongoProperties mongo) {
return getMongoDbFactory(mongo);
}
@Bean
public MongoDbFactory secondaryFactory(final MongoProperties mongo) {
return getMongoDbFactory(mongo);
}
public <T, ID extends Serializable> MongoEntityInformation<T, ID> entityInformationFor(MongoPersistentEntity<T> entity,
Class<ID> idType) {
return new MappingMongoEntityInformation<>(entity, idType);
}
private SimpleMongoDbFactory getMongoDbFactory(MongoProperties mongo) {
MongoCredential mongoCredential = MongoCredential.createCredential(mongo.getUsername(), mongo.getAuthenticationDatabase(), mongo.getPassword());
List<MongoCredential> mongoCredentialList = Collections.singletonList(mongoCredential);
ServerAddress serverAddress = new ServerAddress(mongo.getHost(), mongo.getPort());
MongoClient mongoClient = new MongoClient(serverAddress, mongoCredentialList);
return new SimpleMongoDbFactory(mongoClient,
mongo.getDatabase());
}
}
我的模特:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "products")
public class ProductModel {
@Id
private String id;
@Field(value = "name")
private String name;
}
但是我的 SimpleMongoRepository 配置中有一个问题,在这一行
MongoPersistentEntity<ProductModel> mongoPersistentEntity = new BasicMongoPersistentEntity<>(typeInformation);
idProperty 配置为 null,然后在使用它的后续方法中我得到 NPE。如何解决这个问题?
java.lang.NullPointerException: null
at org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation.getIdAttribute(MappingMongoEntityInformation.java:101) ~[spring-data-mongodb-1.10.9.RELEASE.jar:na]
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.findAll(SimpleMongoRepository.java:211) ~[spring-data-mongodb-1.10.9.RELEASE.jar:na]
at productcatalog.repository.MongoRepositoryImpl.findAll(MongoRepositoryImpl.java:97) ~[classes/:na]
at productcatalog.service.impl.ProductServiceImpl.getProductsByIds(ProductServiceImpl.java:36) ~[classes/:na]
at productcatalog.controller.ProductCatalogController.getProductsByIds(ProductCatalogController.java:90) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:8.5.23]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:8.5.23]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
我得到了存储库:
public class MongoRepositoryImpl<T, K extends Serializable> implements MongoRepository<T, K> {
private SimpleMongoRepository<T, K> primaryRepository;
private SimpleMongoRepository<T, K> secondaryRepository;
private SimpleMongoRepository<T, K> actualSource;
private ReadWriteLock lock = new ReentrantReadWriteLock();
private Lock writeLock = lock.writeLock();
private Lock readLock = lock.readLock();
private static final Integer DEFAULT_SIZE = 10;
public MongoRepositoryImpl(SimpleMongoRepository<T, K> primaryRepository, SimpleMongoRepository<T, K> secondaryRepository) {
this.primaryRepository = primaryRepository;
this.secondaryRepository = secondaryRepository;
actualSource = primaryRepository;
}
@Override
public T findOne(K id) {
T findResult;
try {
readLock.lock();
findResult = actualSource.findOne(id);
} finally {
readLock.unlock();
}
return findResult;
}
@Override
public List<T> findAll() {
List<T> result;
try {
readLock.lock();
result = actualSource.findAll();
} finally {
readLock.unlock();
}
return result;
}
@Override
public Iterable<T> findAll(Iterable<K> ids) {
Iterable<T> result;
try {
readLock.lock();
result = actualSource.findAll(ids);
} finally {
readLock.unlock();
}
return result;
}
除了 findAll (Iterable ids) 之外的所有方法都有效,当我使用这个方法时,我得到了 NPE 因为 idProperty = null;我该如何解决这个问题?
我遇到了同样的挑战,不幸的是找不到一个像样的例子来说明如何做到这一点。
正如您从堆栈跟踪中看到的那样,SimpleMongoRepository
在内部保持 MongoEntityInformation
,并且在 3 种情况下它明确搜索 Id 属性:findAllById()
、existsById()
deleteById()
最终调用 entityInformation.getIdAttribute()
。因此,您必须确保它熟悉您的实体及其 Id 属性。
你是这样操作的:
@Bean("primary")
public SimpleMongoRepository<ProductModel, String> getPrimaryProductRepository() {
TypeInformation<ProductModel> typeInformation = ClassTypeInformation.from(ProductModel.class);
BasicMongoPersistentEntity<ProductModel> mongoPersistentEntity = new BasicMongoPersistentEntity<ProductModel>(typeInformation);
//add Id-property, o/w SimpleMongoRepository asks (e.g. delete()) getIdQuery(id) and we fail on `entityInformation.getIdAttribute()`
Class<ProductModel> aClass = ProductModel.class;
Field field = null;
try
{
field = aClass.getDeclaredField("id");
}
catch (NoSuchFieldException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Property property = Property.of(ClassTypeInformation.from(ProductModel.class), field);
MongoPersistentProperty idProperty = new BasicMongoPersistentProperty(property , mongoPersistentEntity, SimpleTypeHolder.DEFAULT, null);
mongoPersistentEntity.addPersistentProperty(idProperty);
MongoEntityInformation<ProductModel, String> mongoEntityInformation = new MappingMongoEntityInformation<ProductModel, String>(mongoPersistentEntity);
return new SimpleMongoRepository<>(mongoEntityInformation, primaryMongoTemplate());
}
...与 'secondary' 相同。
希望对您有所帮助。
我认为您需要 org.springframework.data.mongodb.repository.support.MongoRepositoryFactory
.
在您的配置中设置工厂 class:
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(MultipleMongoProperties.class)
@EnableMongoRepositories(basePackages = "productcatalog.repository", repositoryFactoryBeanClass = MultipleMongoRepositoryFactoryBean.class)
public class MultipleMongoConfig {
/* ...code... */
}
然后,在您的 MultipleMongoRepositoryFactoryBean
:
public class MultipleMongoRepositoryFactoryBean<R extends MongoRepository<T, I>, T, I extends Serializable> extends MongoRepositoryFactoryBean<R, T, I> {
protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
return new MultipleMongoRepositoryFactory<T, I>(operations);
}
}
然后根据元数据在 MongoRepositoryFactory
中创建自己的一组存储库。
public class MultipleMongoRepositoryFactory<T, ID extends Serializable> extends MongoRepositoryFactory {
private final MongoOperations mongoOperations;
public MultipleMongoRepositoryFactory(MongoOperations mongoOperations) {
super(mongoOperations);
}
@Override
protected Object getTargetRepository(RepositoryMetadata metadata) {
/* Add personalyzed stuff here */
return super.getTargetRepository(metadata);
}
}
请注意 MongoRepositoryFactory::getEntityInformation(EntityMetadata)
有一个方法 returns MongoEntityInformation
,它实际上是从您的配置中抛出异常。因此,如果你真的需要手动配置你的存储库,你可以尝试注入 MongoRepositoryFactory
.
请注意,仅当您需要在存储库实现上实现特定内容时才需要这样做。如果您只使用 Spring 数据提供的默认接口,则不需要像这样。
编辑: 您可以查看 Spring Data 的文档以获取更多信息。 https://docs.spring.io/spring-data/mongodb/docs/1.6.4.RELEASE/reference/html/#repositories.custom-implementations. This was retrieved from version 1.6.4, which is the one I experienced the same problem as yourself. For the current release, please refer to https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.custom-implementations.