private void checkForIndexes(final MongoPersistentEntity<?> entity) { Class<?> type = entity.getType(); if (!classesSeen.containsKey(type)) { this.classesSeen.put(type, Boolean.TRUE); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Analyzing class " + type + " for index information."); } checkForAndCreateIndexes(entity); } }
/** * Creates a new {@link MongoPersistentEntityIndexCreator} for the given {@link MongoMappingContext} and * {@link MongoDbFactory}. * * @param mappingContext must not be {@literal null}. * @param mongoDbFactory must not be {@literal null}. * @param indexResolver must not be {@literal null}. */ public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext, IndexOperationsProvider indexOperationsProvider, IndexResolver indexResolver) { Assert.notNull(mappingContext, "MongoMappingContext must not be null!"); Assert.notNull(indexOperationsProvider, "IndexOperationsProvider must not be null!"); Assert.notNull(indexResolver, "IndexResolver must not be null!"); this.indexOperationsProvider = indexOperationsProvider; this.mappingContext = mappingContext; this.indexResolver = indexResolver; for (MongoPersistentEntity<?> entity : mappingContext.getPersistentEntities()) { checkForIndexes(entity); } }
private void checkForAndCreateIndexes(MongoPersistentEntity<?> entity) { if (entity.isAnnotationPresent(Document.class)) { for (IndexDefinition indexDefinition : indexResolver.resolveIndexFor(entity.getTypeInformation())) { JustOnceLogger.logWarnIndexCreationConfigurationChange(this.getClass().getName()); IndexDefinitionHolder indexToCreate = indexDefinition instanceof IndexDefinitionHolder ? (IndexDefinitionHolder) indexDefinition : new IndexDefinitionHolder("", indexDefinition, entity.getCollection()); createIndex(indexToCreate); } } }
/** * Inspects the given {@link ApplicationContext} for {@link MongoPersistentEntityIndexCreator} and those in turn if * they were registered for the current {@link MappingContext}. If no creator for the current {@link MappingContext} * can be found we manually add the internally created one as {@link ApplicationListener} to make sure indexes get * created appropriately for entity types persisted through this {@link MongoTemplate} instance. * * @param context must not be {@literal null}. */ private void prepareIndexCreator(ApplicationContext context) { String[] indexCreators = context.getBeanNamesForType(MongoPersistentEntityIndexCreator.class); for (String creator : indexCreators) { MongoPersistentEntityIndexCreator creatorBean = context.getBean(creator, MongoPersistentEntityIndexCreator.class); if (creatorBean.isIndexCreatorFor(mappingContext)) { return; } } if (context instanceof ConfigurableApplicationContext && indexCreator != null) { ((ConfigurableApplicationContext) context).addApplicationListener(indexCreator); } }
void createIndex(IndexDefinitionHolder indexDefinition) { try { IndexOperations indexOperations = indexOperationsProvider.indexOps(indexDefinition.getCollection()); indexOperations.ensureIndex(indexDefinition); } catch (UncategorizedMongoDbException ex) { if (ex.getCause() instanceof MongoException && MongoDbErrorCodes.isDataIntegrityViolationCode(((MongoException) ex.getCause()).getCode())) { IndexInfo existingIndex = fetchIndexInformation(indexDefinition); String message = "Cannot create index for '%s' in collection '%s' with keys '%s' and options '%s'."; if (existingIndex != null) { message += " Index already defined as '%s'."; } throw new DataIntegrityViolationException( String.format(message, indexDefinition.getPath(), indexDefinition.getCollection(), indexDefinition.getIndexKeys(), indexDefinition.getIndexOptions(), existingIndex), ex.getCause()); } throw ex; } }
/** * Constructor used for a basic template configuration. * * @param mongoDbFactory must not be {@literal null}. * @param mongoConverter */ public MongoTemplate(MongoDbFactory mongoDbFactory, @Nullable MongoConverter mongoConverter) { Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null!"); this.mongoDbFactory = mongoDbFactory; this.exceptionTranslator = mongoDbFactory.getExceptionTranslator(); this.mongoConverter = mongoConverter == null ? getDefaultMongoConverter(mongoDbFactory) : mongoConverter; this.queryMapper = new QueryMapper(this.mongoConverter); this.updateMapper = new UpdateMapper(this.mongoConverter); this.schemaMapper = new MongoJsonSchemaMapper(this.mongoConverter); this.projectionFactory = new SpelAwareProxyProjectionFactory(); this.operations = new EntityOperations(this.mongoConverter.getMappingContext()); this.propertyOperations = new PropertyOperations(this.mongoConverter.getMappingContext()); // We always have a mapping context in the converter, whether it's a simple one or not mappingContext = this.mongoConverter.getMappingContext(); // We create indexes based on mapping events if (mappingContext instanceof MongoMappingContext) { MongoMappingContext mappingContext = (MongoMappingContext) this.mappingContext; if (mappingContext.isAutoIndexCreation()) { indexCreator = new MongoPersistentEntityIndexCreator(mappingContext, this); eventPublisher = new MongoMappingEventPublisher(indexCreator); mappingContext.setApplicationEventPublisher(eventPublisher); } } }
/** * Inspects the given {@link ApplicationContext} for {@link MongoPersistentEntityIndexCreator} and those in turn if * they were registered for the current {@link MappingContext}. If no creator for the current {@link MappingContext} * can be found we manually add the internally created one as {@link ApplicationListener} to make sure indexes get * created appropriately for entity types persisted through this {@link MongoTemplate} instance. * * @param context must not be {@literal null}. */ private void prepareIndexCreator(ApplicationContext context) { String[] indexCreators = context.getBeanNamesForType(MongoPersistentEntityIndexCreator.class); for (String creator : indexCreators) { MongoPersistentEntityIndexCreator creatorBean = context.getBean(creator, MongoPersistentEntityIndexCreator.class); if (creatorBean.isIndexCreatorFor(mappingContext)) { return; } } if (context instanceof ConfigurableApplicationContext && indexCreator != null) { ((ConfigurableApplicationContext) context).addApplicationListener(indexCreator); } }
void createIndex(IndexDefinitionHolder indexDefinition) { try { IndexOperations indexOperations = indexOperationsProvider.indexOps(indexDefinition.getCollection()); indexOperations.ensureIndex(indexDefinition); } catch (UncategorizedMongoDbException ex) { if (ex.getCause() instanceof MongoException && MongoDbErrorCodes.isDataIntegrityViolationCode(((MongoException) ex.getCause()).getCode())) { IndexInfo existingIndex = fetchIndexInformation(indexDefinition); String message = "Cannot create index for '%s' in collection '%s' with keys '%s' and options '%s'."; if (existingIndex != null) { message += " Index already defined as '%s'."; } throw new DataIntegrityViolationException( String.format(message, indexDefinition.getPath(), indexDefinition.getCollection(), indexDefinition.getIndexKeys(), indexDefinition.getIndexOptions(), existingIndex), ex.getCause()); } throw ex; } }
/** * Constructor used for a basic template configuration. * * @param mongoDbFactory must not be {@literal null}. * @param mongoConverter */ public MongoTemplate(MongoDbFactory mongoDbFactory, @Nullable MongoConverter mongoConverter) { Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null!"); this.mongoDbFactory = mongoDbFactory; this.exceptionTranslator = mongoDbFactory.getExceptionTranslator(); this.mongoConverter = mongoConverter == null ? getDefaultMongoConverter(mongoDbFactory) : mongoConverter; this.queryMapper = new QueryMapper(this.mongoConverter); this.updateMapper = new UpdateMapper(this.mongoConverter); this.schemaMapper = new MongoJsonSchemaMapper(this.mongoConverter); this.projectionFactory = new SpelAwareProxyProjectionFactory(); this.operations = new EntityOperations(this.mongoConverter.getMappingContext()); this.propertyOperations = new PropertyOperations(this.mongoConverter.getMappingContext()); // We always have a mapping context in the converter, whether it's a simple one or not mappingContext = this.mongoConverter.getMappingContext(); // We create indexes based on mapping events if (mappingContext instanceof MongoMappingContext) { indexCreator = new MongoPersistentEntityIndexCreator((MongoMappingContext) mappingContext, this); eventPublisher = new MongoMappingEventPublisher(indexCreator); if (mappingContext instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher); } } }
public void onApplicationEvent(MappingContextEvent<?, ?> event) { if (!event.wasEmittedBy(mappingContext)) { return; } PersistentEntity<?, ?> entity = event.getPersistentEntity(); // Double check type as Spring infrastructure does not consider nested generics if (entity instanceof MongoPersistentEntity) { checkForIndexes((MongoPersistentEntity<?>) entity); } }
private void checkForAndCreateIndexes(MongoPersistentEntity<?> entity) { if (entity.isAnnotationPresent(Document.class)) { for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexFor(entity.getTypeInformation())) { createIndex(indexToCreate); } } }
private void checkForIndexes(final MongoPersistentEntity<?> entity) { Class<?> type = entity.getType(); if (!classesSeen.containsKey(type)) { this.classesSeen.put(type, Boolean.TRUE); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Analyzing class " + type + " for index information."); } checkForAndCreateIndexes(entity); } }
/** * Creates a new {@link MongoPersistentEntityIndexCreator} for the given {@link MongoMappingContext} and * {@link MongoDbFactory}. * * @param mappingContext must not be {@literal null}. * @param mongoDbFactory must not be {@literal null}. * @param indexResolver must not be {@literal null}. */ public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext, IndexOperationsProvider indexOperationsProvider, IndexResolver indexResolver) { Assert.notNull(mappingContext, "MongoMappingContext must not be null!"); Assert.notNull(indexOperationsProvider, "IndexOperationsProvider must not be null!"); Assert.notNull(indexResolver, "IndexResolver must not be null!"); this.indexOperationsProvider = indexOperationsProvider; this.mappingContext = mappingContext; this.indexResolver = indexResolver; for (MongoPersistentEntity<?> entity : mappingContext.getPersistentEntities()) { checkForIndexes(entity); } }
public void onApplicationEvent(MappingContextEvent<?, ?> event) { if (!event.wasEmittedBy(mappingContext)) { return; } PersistentEntity<?, ?> entity = event.getPersistentEntity(); // Double check type as Spring infrastructure does not consider nested generics if (entity instanceof MongoPersistentEntity) { checkForIndexes((MongoPersistentEntity<?>) entity); } }