복붙노트

[SPRING] @Document가있는 몽고 멀티 입주

SPRING

@Document가있는 몽고 멀티 입주

이것은 다음과 관련이있다. @Document 주석의 MongoDB 및 SpEL 표현식

이것은 내 mongo 템플릿을 만드는 방법입니다.

@Bean
public MongoDbFactory mongoDbFactory() throws UnknownHostException {
    String dbname = getCustid();
    return new SimpleMongoDbFactory(new MongoClient("localhost"), "mydb");
}

@Bean
MongoTemplate mongoTemplate() throws UnknownHostException {
    MappingMongoConverter converter = 
            new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext());
    return new MongoTemplate(mongoDbFactory(), converter);
}

나는 임차인 클래스를 가지고있다.

@Component("tenantProvider")
public class TenantProvider {

    public String getTenantId() {
      --custome Thread local logic for getting a name
    }
}

그리고 내 도메인 클래스

    @Document(collection = "#{@tenantProvider.getTenantId()}_device")
     public class Device {
    -- my fields here
    }

보시다시피, 게시물에 지정된대로 mongotemplate을 만들었지 만, 여전히 아래 오류가 나타납니다.

내가 뭘 잘못하고 있죠?

해결법

  1. ==============================

    1.마침내 왜이 문제가 발생하는지 알아 냈습니다.

    마침내 왜이 문제가 발생하는지 알아 냈습니다.

    Servlet 3 초기화를 사용할 때 다음과 같이 mongo 컨텍스트에 응용 프로그램 컨텍스트를 추가했는지 확인하십시오

        @Autowired
    private ApplicationContext appContext;
    
    public MongoDbFactory mongoDbFactory() throws UnknownHostException {
        return new SimpleMongoDbFactory(new MongoClient("localhost"), "apollo-mongodb");
    }
    
    @Bean
    MongoTemplate mongoTemplate() throws UnknownHostException {
        final MongoDbFactory factory = mongoDbFactory();
    
        final MongoMappingContext mongoMappingContext = new MongoMappingContext();
        mongoMappingContext.setApplicationContext(appContext);
    
        // Learned from web, prevents Spring from including the _class attribute
        final MappingMongoConverter converter = new MappingMongoConverter(factory, mongoMappingContext);
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
    
        return new MongoTemplate(factory, converter);
    }
    

    컨텍스트의 autowiring을 확인하고 또한 mongoMappingContext.setApplicationContext (appContext);

    이 두 라인을 통해 구성 요소가 멀티 테넌트 모드에서 올바르게 사용되도록 배선 할 수있었습니다.

  2. ==============================

    2.관련 문제 에서처럼 mongoTemplate을 구성한 경우 생각할 수있는 것은 다음과 같습니다.

    관련 문제 에서처럼 mongoTemplate을 구성한 경우 생각할 수있는 것은 다음과 같습니다.

    <context:component-scan base-package="com.tenantprovider.package" />
    

    또는 특수 효과를 사용하려는 경우 :

    @ComponentScan(basePackages = "com.tenantprovider.package")
    

    테넌트 제공자 패키지를 스캔하지 않았을 수 있습니다.

    전의:

    @ComponentScan(basePackages = "com.tenantprovider.package")
    @Document(collection = "#{@tenantProvider.getTenantId()}_device")
    public class Device {
        -- my fields here
    }
    
  3. ==============================

    3.위의 대답은 내 경우에 부분적으로 만 작용했습니다.

    위의 대답은 내 경우에 부분적으로 만 작용했습니다.

    나는 같은 문제로 어려움을 겪어 왔고, 마침내 실현 된 런타임 실행 경로 (RepositoryFactorySupport가 AbstractMongoQuery를 사용하여 MongoDB를 쿼리 할 때 SimpleMongoRepository 대신 SpringData에서 제공하는 "out of the box"메소드에서 SimpleMongoRepository를 사용함) ) AbstractMongoQuery에서 사용되는 MongoQueryMethod에 속하는 MongoEntityMetadata 유형의 메타 데이터 객체는 getEntityInformation ()이라는 메소드에서 한 번만 업데이트됩니다.

    이 '상태있는'bean에 대한 참조를 보유하고있는 MongoQueryMethod 객체는 인프라 코드에 의해 풀링 / 캐싱 된 것으로 보이기 때문에 @Document 주석은 항상 작동하지 않습니다.

    지금까지 제가 개발자로 알고있는 한가지 선택 사항이 있습니다. @Repository 빈에서 직접 MongoOperations를 사용하여 런타임시 Spel로 평가되는 올바른 컬렉션 이름을 지정할 수 있습니다.

    MongoEntityMetadata에 null 컬렉션 이름을 설정하여이 동작을 수정하기 위해 AOP를 사용하려고 시도했지만 실행 인터페이스를 구현하는 AbstractMongoQuery 내부 클래스의 변경 사항도 확인해야합니다. MongoEntityMetadata 컬렉션 이름이 null이므로 다른 MongoTemplate 메서드 서명을 사용합니다. MongoTemplate은 개인 메소드를 사용하여 올바른 컬렉션 이름을 추측 할만큼 똑똑합니다.

    private <T> String determineEntityCollectionName(T obj)
    

    나는 봄의 jira에서 티켓을 만들었습니다. https://jira.spring.io/browse/DATAMONGO-1043

  4. from https://stackoverflow.com/questions/19807733/mongodb-multi-tenacy-spel-with-document by cc-by-sa and MIT license