gpt4 book ai didi

java - 创建索引时出现异常 - Spring Data MongoDB

转载 作者:行者123 更新时间:2023-12-02 03:14:08 25 4
gpt4 key购买 nike

我使用 Spring-Data 和 Spring-Data MongoDB 来使用 @CompoundIndexes 注释来映射实体类,在该注释中我使用名称及其定义来指定索引。在我的生产环境中,我决定需要根据实际数据更改索引的一些属性。现在,每次我的应用程序启动时,它都会无法加载,因为无法创建与注释结果中的规范相匹配的索引,并且在初始化过程中会引发该异常(如下所示)。

是否有配置 spring data 和 mongodb 以便记录这些异常但不会导致容器启动失败?

Exception while creating index
! com.mongodb.MongoCommandException: Command failed with error 86: 'Trying to create an index with same name event_source_link_type_at_id_IDX with different key spec **** vs existing spec *****' on server 127.0.0.1:27017. The full response is { "ok" : 0.0, "errmsg" : "Trying to create an index with same name event_source_link_type_at_id_IDX with different key spec **** vs existing spec *****", "code" : 86 }
! at com.mongodb.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:115) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.connection.CommandProtocol.execute(CommandProtocol.java:114) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:159) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:286) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.connection.DefaultServerConnection.command(DefaultServerConnection.java:173) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:215) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:198) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:170) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.CreateIndexesOperation$1.call(CreateIndexesOperation.java:116) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.CreateIndexesOperation$1.call(CreateIndexesOperation.java:111) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:230) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:221) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.CreateIndexesOperation.execute(CreateIndexesOperation.java:111) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.operation.CreateIndexesOperation.execute(CreateIndexesOperation.java:66) ~[mongodb-driver-core-3.2.2.jar:na]
! at com.mongodb.Mongo.execute(Mongo.java:781) ~[mongodb-driver-3.2.2.jar:na]
! at com.mongodb.Mongo$2.execute(Mongo.java:764) ~[mongodb-driver-3.2.2.jar:na]
! at com.mongodb.DBCollection.createIndex(DBCollection.java:1541) ~[mongodb-driver-3.2.2.jar:na]
! at org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator.createIndex(MongoPersistentEntityIndexCreator.java:142) [spring-data-mongodb-1.8.4.RELEASE.jar:na]

最佳答案

事实证明这并不像我想象的那么容易,但可以通过一些额外的类(class)来完成。

首先,您需要重写创建索引的类并重写创建索引的方法,捕获匹配的异常并仅记录它们。

不幸的是,它是受包保护的,因此您需要在与我们扩展的类相同的包中创建一个类。

package org.springframework.data.mongodb.core.index;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;

public class ExceptionIgnoringIndexCreator extends MongoPersistentEntityIndexCreator {

//assuming SLF4J as your logger otherwise, put your logger here
private static final Logger LOG = LoggerFactory.getLogger(ExceptionIgnoringIndexCreator.class);

public ExceptionIgnoringIndexCreator(MongoMappingContext mappingContext, MongoDbFactory mongoDbFactory) {
super(mappingContext, mongoDbFactory);
}

@Override
void createIndex(MongoPersistentEntityIndexResolver.IndexDefinitionHolder indexDefinition) {
try {
super.createIndex(indexDefinition);
} catch (final RuntimeException exp) {
final RuntimeException trans = translate(exp);
if (trans != null) {
throw trans;
} else {
LOG.warn("Exception while creating index", exp);
}
}
}

protected RuntimeException translate(final RuntimeException exp) {
if (exp == null || exp.getMessage().contains("Cannot create index")) {
return null;
}
return exp;
}
}

索引创建是由 MongoMappingContext 使用 ApplicationEventPublisherInterface 发布的事件触发的。我们需要一个类,我们可以延迟地将另一个 ApplicationEventPublisher 设置为委托(delegate),接口(interface)的两个方法将其调用委托(delegate)给该委托(delegate)。

public class DelegatingPublisher implements ApplicationEventPublisher {

private ApplicationEventPublisher delegate;

@Override
public void publishEvent(ApplicationEvent event) {
delegate.publishEvent(event);
}

@Override
public void publishEvent(Object event) {
delegate.publishEvent(event);
}

public void setDelegate(ApplicationEventPublisher delegate) {
this.delegate = delegate;
}

}

通常,您使用扩展 AbstractMongoConfig 并覆盖“mongo()”方法的类来配置 spring data mongoDB。

负责发布初始化索引的消息的组件是从“mongoMappingContext()”返回的组件,因此您需要重写该方法并扩展默认的 MongoMappingContext ,重写设置事件发布者的方法并传递我们的新方法委托(delegate)发布商代替它。

@Configuration
@EnableMongoRepositories("com.my.company")
public class MyMongoConfig extends AbstractMongoConfiguration {
...
@Override
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
final DelegatingPublisher dep = new DelegatingPublisher();
final MongoMappingContext mappingContext = new MongoMappingContext() {
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
super.setApplicationEventPublisher(dep);
}
};
mappingContext.setInitialEntitySet(getInitialEntitySet());
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());

try {
final MongoPersistentEntityIndexCreator indexCreator = new ExceptionIgnoringIndexCreator(mappingContext, mongoDbFactory());
dep.setDelegate(new MongoMappingEventPublisher(indexCreator));
return mappingContext;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
...
}

如果您使用基于 XML 的配置,则还需要一个类和指定的配置

public class EventDelegatingMongoMappingContext extends MongoMappingContext {

private ApplicationEventPublisher publisher;

public EventDelegatingMongoMappingContext(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}

@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
super.setApplicationEventPublisher(publisher);
}
}
<mongo:db-factory id="mongoDbFactory"
host="localhost"
port="27017"
dbname="database"
username="mycompany"
password="secret"/>

<bean id="delegatingPublisher" class="com.my.company.DelegatingPublisher">
<property name="delegate" ref="mappingEventPublisher" />
</bean>

<!-- Must be named 'mongoMappingContext' to be recognized up -->
<bean id="mongoMappingContext" class="com.my.company.EventDelegatingMongoMappingContext">
<constructor-arg>
<bean ref="delegatingPublisher" />
</constructor-arg>
</bean>

<bean id="mongoIndexCreator" class="org.springframework.data.mongodb.core.index.ExceptionIgnoringIndexCreator">
<constructor-arg>
<bean ref="mongoMappingContext"/>
</constructor-arg>
<constructor-arg>
<bean ref="mongoDbFactory"/>
</constructor-arg>
</bean>

<bean id="mappingEventPublisher" class="org.springframework.data.mongodb.core.index.MongoMappingEventPublisher">
<constructor-arg>
<bean ref="mongoIndexCreator"/>
</constructor-arg>
</bean>

关于java - 创建索引时出现异常 - Spring Data MongoDB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40568777/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com