2016-11-12 2 views
0

Spring 데이터와 함께 Spring-Data MongoDB를 사용하여 @CompoundIndexes 주석을 사용하여 엔티티 클래스를 매핑합니다. 여기서는 이름과 정의가 모두있는 인덱스를 지정합니다. 제작 환경에서는 실제 데이터를 기반으로 인덱스의 일부 특성을 변경해야한다고 결정했습니다. 이제는 애플리케이션이 시작될 때마다 주석 결과의 사양과 일치하는 색인을 생성하지 못하고 초기화 프로세스 중에 예외가 발생하기 때문에로드가 실패합니다 (아래 참조).인덱스 생성 중 예외 - Spring Data MongoDB

이러한 예외가 기록되지만 컨테이너의 시작을 실패하지 않도록 스프링 데이터와 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] 

답변

0

이것은 생각보다 쉽지는 않지만 몇 가지 추가 수업으로 할 수 있습니다.

먼저 인덱스를 만드는 클래스를 재정의하고 인덱스를 만드는 메서드를 덮어 쓰고 일치하는 예외를 트래핑 한 다음 로깅 만합니다.

불행히도 패키지 보호 기능을 제공하므로 확장 할 클래스와 동일한 패키지에 클래스를 만들어야합니다.

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; 
    } 
} 

인덱스 생성은 ApplicationEventPublisherInterface를 사용하여 MongoMappingContext에 의해 게시 된 이벤트에 의해 트리거됩니다. 인터페이스의 두 메소드가 호출을 위임 할 다른 ApplicationEventPublisher를 지연적으로 설정할 수있는 클래스가 필요합니다.

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를 확장하고 "몽고()"메소드를 오버라이드 (override) 클래스를 사용하여 스프링 데이터 MongoDB를 구성합니다.

인덱스를 초기화하는 메시지를 게시하는 구성 요소는 "mongoMappingContext()"에서 반환 된 구성 요소이므로 해당 메서드를 재정의하고 기본 MongoMappingContext를 확장하여 이벤트 게시자를 설정 한 메서드를 재정의해야합니다. 새 대리인 게시자가 필요합니다.

@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> 
관련 문제