Paul Zhu
Paul Zhu

Reputation: 81

Spring Boot Mongo Data - How to Set Naming Strategy

Dear Stack Overflow Community,

I am currently working on a Spring Boot project where the variable names are written in camel case. I also have a MongoDB database with fields written in snake case. Currently I am using @Field annotation provided by Spring Mongo Data to map each variable to its corresponding logical name like this:

@Field("var_name")
private String varName;

My question is - Is there a way to configure globally an automatic Camel Case to Snake Case conversion in Spring Mongo Data? If I have a model with many instance variables, it would be trivial to add a @Field annotation for each of them.

Thank you in advance.

Upvotes: 3

Views: 3163

Answers (3)

Ganesh Jadhav
Ganesh Jadhav

Reputation: 802

There are 2 ways to do this at global level:

  1. To override MongoMappingContext:
public class MongoConfig extends AbstractReactiveMongoConfiguration {

  @Override
  public MongoClient reactiveMongoClient() {
    return MongoClients.create(uri);
  }

  @Bean
  @Override
  public MongoMappingContext mongoMappingContext(MongoCustomConversions customConversions) throws ClassNotFoundException {
    MongoMappingContext mappingContext = new MongoMappingContext();
    mappingContext.setInitialEntitySet(this.getInitialEntitySet());
    mappingContext.setSimpleTypeHolder(customConversions.getSimpleTypeHolder());
    mappingContext.setFieldNamingStrategy(new SnakeCaseFieldNamingStrategy()); //NOTE this line
    mappingContext.setAutoIndexCreation(this.autoIndexCreation());
    return mappingContext;
  }

Here we override the mappingContext and pass snakeCasing, default for which is camel.

  1. To update codecRegistry
public MongoClient reactiveMongoClient() {
    return MongoClients.create(
        MongoClientSettings.builder().applyConnectionString(new ConnectionString(uri))
            .codecRegistry(codecRegistry())
            .build());
  }
  public CodecRegistry codecRegistry() {
    List<Convention> conventions = Collections.<Convention>singletonList(
        classModelBuilder -> {
          for (PropertyModelBuilder<?> fieldModelBuilder : classModelBuilder.getPropertyModelBuilders()) {
            fieldModelBuilder.discriminatorEnabled(false);
            fieldModelBuilder.readName(
                fieldModelBuilder.getName()
                    .replaceAll("([^_A-Z])([A-Z])", "$1_$2").toLowerCase());
            fieldModelBuilder.writeName(
                fieldModelBuilder.getName()
                    .replaceAll("([^_A-Z])([A-Z])", "$1_$2").toLowerCase());
          }

          classModelBuilder.enableDiscriminator(true);
          classModelBuilder.discriminatorKey("_cls");
          classModelBuilder.discriminator(classModelBuilder.getType().getSimpleName()
              .replaceAll("([^_A-Z])([A-Z])", "$1_$2").toLowerCase());
        });
    CodecProvider pojoCodecProvider =
        PojoCodecProvider.builder().conventions(conventions).build();
    return fromRegistries(getDefaultCodecRegistry(), fromProviders(pojoCodecProvider));
  }

The 2nd one is taken from the test mentioned here, and better explanation is here in the docs
Though I couldnt get 2nd one working but as per this comment it should ideally.

Reference: https://github.com/mongodb/mongo-java-driver/blob/r3.5.0/bson/src/test/unit/org/bson/codecs/pojo/PojoCustomTest.java#L136

Upvotes: 1

Nelson
Nelson

Reputation: 59

For Spring Boot, you can add "field-naming-strategy" into your application.yml like this:

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      username: xxxxx
      password: yyyyy
      authentication-database: admin
      database: my_mongo_db
      field-naming-strategy: org.springframework.data.mapping.model.SnakeCaseFieldNamingStrategy

Upvotes: 3

Qiuxuan Zhang
Qiuxuan Zhang

Reputation: 1

Have you tried mappingContext.setFieldNamingStrategy(new SnakeCaseFieldNamingStrategy()) in your Mongo configuration class?

Upvotes: 0

Related Questions