Spring Data MongoDb: MappingMongoConverter删除_class

44

默认的 MappingMongoConverter 会向数据库中的每个对象添加一个自定义类型键 ("_class")。所以,如果我创建了一个 Person:

package my.dto;
public class Person {
    String name;
    public Person(String name) {
        this.name = name; 
    }
}

并将其保存到数据库中:

MongoOperations ops = new MongoTemplate(new Mongo(), "users");
ops.insert(new Person("Joe"));

在Mongo中得到的结果对象将是:

{ "_id" : ObjectId("4e2ca049744e664eba9d1e11"), "_class" : "my.dto.Person", "name" : "Joe" }

问题:

  1. 将Person类移动到不同的命名空间有什么影响?

  2. 是否可能在不为Person类编写独特的转换器的情况下,使对象不会被"_class"键污染?


1
那么这是怎么回事呢?有没有办法防止“_class”字段被存储在MongoDB中? - hodgesz
13个回答

1
@Configuration
public class MongoConfig {

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Value("${spring.data.mongodb.host}")
    private String host;

    public @Bean MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(host), database);
    }

    public @Bean MongoTemplate mongoTemplate() throws Exception {

        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()),
                new MongoMappingContext());
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));

        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), converter);

        return mongoTemplate;

    }

}

1
欢迎来到Stack Overflow!虽然这段代码片段可能解决了问题,但它并没有解释为什么或者如何回答这个问题。请在您的代码中包含解释,因为这真的有助于提高您的帖子质量。记住,您正在为未来的读者回答问题,而这些人可能不知道您的代码建议的原因。 - Samuel Philipp

0

我尝试了上面的解决方案,其中一些与审计结合使用时不起作用,而且似乎没有正确设置MongoCustomConversions

对我有效的解决方案如下:

@Configuration
public class MongoConfig {

    @Bean
    public MappingMongoConverter mappingMongoConverterWithCustomTypeMapper(
            MongoDatabaseFactory factory,
            MongoMappingContext context,
            MongoCustomConversions conversions) {
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
        MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
        mappingConverter.setCustomConversions(conversions);

        /**
         * replicate the way that Spring
         * instantiates a {@link DefaultMongoTypeMapper}
         * in {@link MappingMongoConverter#MappingMongoConverter(DbRefResolver, MappingContext)}
         */
        CustomMongoTypeMapper customTypeMapper = new CustomMongoTypeMapper(
                context,
                mappingConverter::getWriteTarget);
        mappingConverter.setTypeMapper(customTypeMapper);
        return mappingConverter;
    }
}

public class CustomMongoTypeMapper extends DefaultMongoTypeMapper {

    public CustomMongoTypeMapper(
            MappingContext<? extends PersistentEntity<?, ?>, ?> mappingContext,
            UnaryOperator<Class<?>> writeTarget) {
        super(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext, writeTarget);
    } 

    @Override
    public TypeInformation<?> readType(Bson source) {

    /**
     * do your conversion here, and eventually return
     */
    return super.readType(source);
    }
}

作为替代方案,您可以使用一个BeanPostProcessor来检测是否创建了mappingMongoConverter,并在那里添加您的转换器。
类似以下内容:
public class MappingMongoConverterHook implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("mappingMongoConverter" == beanName) {
            ((MappingMongoConverter) bean).setTypeMapper(new CustomMongoTypeMapper());
        }
        return bean;
    }
}

0

你只需要在类定义上添加@TypeAlias注解,而不是更改类型映射器


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接