Spring数据MongoDb:MappingMongoConverter删除_class

Yur*_*sov 32 mongodb spring-data spring-data-mongodb

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

package my.dto;
public class Person {
    String name;
    public Person(String name) {
        this.name = name; 
    }
}
Run Code Online (Sandbox Code Playgroud)

并将其保存到db:

MongoOperations ops = new MongoTemplate(new Mongo(), "users");
ops.insert(new Person("Joe"));
Run Code Online (Sandbox Code Playgroud)

mongo中的结果对象将是:

{ "_id" : ObjectId("4e2ca049744e664eba9d1e11"), "_class" : "my.dto.Person", "name" : "Joe" }
Run Code Online (Sandbox Code Playgroud)

问题:

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

  2. 是否有可能不用"_class"键污染对象; 没有为Person类编写一个独特的转换器?

Oli*_*ohm 28

所以这就是故事:我们默认添加类型作为某种暗示实际实例化的类.由于您必须通过管道输入文档来进行读取,MongoTemplate因此有两种可能的选择:

  1. 您可以输入可以分配给实际存储类型的类型.在这种情况下,我们考虑存储的类型,用于创建对象.这里的经典示例是进行多态查询.假设你有一个抽象类Contact和你的Person.然后,您可以查询ContactS和我们基本上必须确定一个类型的实例.
  2. 如果你 - 另一方面 - 传递一个完全不同的类型,我们只是编组到那个给定的类型,而不是实际存储在文档中的类型.这将涵盖您的问题,如果您移动类型会发生什么.

您可能有兴趣观看此票据,其中包含某种可插入类型映射策略,以将类型信息转换为实际类型.这可以简单地节省空间,因为您可能希望将长限定类名减少为几个字母的哈希值.它还允许更复杂的迁移方案,您可能会在其中找到由另一个数据存储客户端生成的完全任意类型的密钥,并将这些密钥绑定到Java类型.

  • Oliver,有没有简单的方法可以在 1.0GA 中删除 _class?[这个](http://forum.springsource.org/showthread.php?112505-Spring-data-MongoDb-MappingMongoConverter-remove-_class) 现在不起作用。看起来最简单的方法是:`((MappingMongoConverter)template.getConverter()).setTypeMapper(new DefaultMongoTypeMapper(null));`。但它丑陋和错误...... (2认同)

mky*_*ong 17

这是我的注释,它的工作原理.

@Configuration
public class AppMongoConfig {

    public @Bean
    MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory(new Mongo(), "databasename");
    }

    public @Bean
    MongoTemplate mongoTemplate() throws Exception {

        //remove _class
        MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext());
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));

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

        return mongoTemplate;

    }

}
Run Code Online (Sandbox Code Playgroud)


Ath*_*lan 6

如果要_class默认禁用属性,但保留指定类的多态性,则可以通过配置来明确定义_class(可选)字段的类型:

@Bean
public MongoTemplate mongoTemplate() throws Exception {
    Map<Class<?>, String> typeMapperMap = new HashMap<>();
    typeMapperMap.put(com.acme.domain.SomeDocument.class, "role");

    TypeInformationMapper typeMapper1 = new ConfigurableTypeInformationMapper(typeMapperMap);

    MongoTypeMapper typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, Arrays.asList(typeMapper1));
    MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext());
    converter.setTypeMapper(typeMapper);

    MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), converter);
    return mongoTemplate;
}
Run Code Online (Sandbox Code Playgroud)

这将仅保留_class指定实体的字段(或您要在构造器中命名的任何字段)。

您也可以编写自己TypeInformationMapper的注释,例如基于注释。如果您通过注释文档,@DocumentType("aliasName")则将通过保留类的别名来保持多态。

我已经在博客上对其进行了简要说明,但是这里有一些快速代码:https : //gist.github.com/athlan/6497c74cc515131e1336


小智 5

<mongo:mongo host="hostname" port="27017">
<mongo:options
...options...
</mongo:mongo>
<mongo:db-factory dbname="databasename" username="user" password="pass"                     mongo-ref="mongo"/>
<bean id="mongoTypeMapper"     class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
<constructor-arg name="typeKey"><null/></constructor-arg>
</bean>
<bean id="mongoMappingContext"      class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
<bean id="mongoConverter"     class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mappingContext" ref="mongoMappingContext" />
<property name="typeMapper" ref="mongoTypeMapper"></property>
</bean>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
<constructor-arg name="mongoConverter" ref="mongoConverter" />
<property name="writeResultChecking" value="EXCEPTION" /> 
</bean>
Run Code Online (Sandbox Code Playgroud)


har*_*vmb 5

虽然 Mkyong 的答案仍然有效,但我想添加我的解决方案版本,因为很少有位被弃用,并且可能处于清理的边缘。

例如:MappingMongoConverter(mongoDbFactory(), new MongoMappingContext())已弃用,赞成new MappingMongoConverter(dbRefResolver, new MongoMappingContext());SimpleMongoDbFactory(new Mongo(), "databasename");赞成new SimpleMongoDbFactory(new MongoClient(), database);

所以,我的最终工作答案没有弃用警告是:

@Configuration
public class SpringMongoConfig {

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

    @Autowired
    private MongoDbFactory mongoDbFactory;

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

    public @Bean MongoTemplate mongoTemplate() throws Exception {

        DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);

        // Remove _class
        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext());
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));

        return new MongoTemplate(mongoDBFactory(), converter);

    }

}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助那些想要一个干净的类并且没有弃用警告的人。