春季数据mongoDB:绘图mappingmongoconverter删除_ class
-
25-10-2019 - |
题
默认值 Mappingmongoconverter 在数据库中的每个对象中添加自定义类型键(“ _Class”)。因此,如果我创造一个人:
package my.dto;
public class Person {
String name;
public Person(String name) {
this.name = name;
}
}
并将其保存到DB:
MongoOperations ops = new MongoTemplate(new Mongo(), "users");
ops.insert(new Person("Joe"));
蒙哥中的结果对象将是:
{ "_id" : ObjectId("4e2ca049744e664eba9d1e11"), "_class" : "my.dto.Person", "name" : "Joe" }
问题:
将人类班级转移到另一个名称空间的含义是什么?
是否可以不用“ _ class”键污染对象;不仅仅为人类班编写独特的转换器?
解决方案
因此,这就是故事:默认情况下,我们将类型添加为某种提示实际上可以实例化的类型。正如您必须在类型的类型中进行管道以将文档读取到Via中 MongoTemplate
无论如何,有两个可能的选择:
- 您可以将实际存储的类型分配给类型。在这种情况下,我们考虑存储的类型,将其用于对象创建。这里的经典示例是进行多态性查询。假设你有一个抽象课
Contact
和你的Person
. 。然后您可以查询Contact
S,我们本质上 必须 确定实例化的类型。 - 如果您(另一方面,我们都会传递到完全不同的类型,我们只需将其纳入给定类型,而不是实际上存储在文档中的类型中。那将解决您的问题,如果您移动类型会发生什么。
您可能有兴趣观看 这张票 它涵盖了某种可插入类型的映射策略,以将类型信息转换为实际类型。这可以单纯地节省空间的目的,因为您可能希望将长期合格的班级名称简化为几个字母的哈希。它还将允许更复杂的迁移方案,您可能会发现另一个数据存储客户端产生的完全任意类型的键并将其绑定到Java类型。
其他提示
这是我的注释,它有效。
@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;
}
}
<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>
如果您想禁用 _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;
}
这将保留 _class
仅针对指定实体的字段(或您想在约束中命名的任何命名)。
你也可以自己写 TypeInformationMapper
例如基于注释。如果您通过注释您的文档 @DocumentType("aliasName")
您将通过保持班级别名来保持多态性。
我在博客上简要解释了, ,但这是一些快速代码:https://gist.github.com/athlan/6497C74CC515131E1336
虽然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);
}
}
希望这可以帮助那些想参加没有折旧警告的干净课程的人。
这是我的一行解决方案:
@Bean
public MongoTemplate mongoTemplateFraud() throws UnknownHostException {
MongoTemplate mongoTemplate = new MongoTemplate(getMongoClient(), dbName);
((MappingMongoConverter)mongoTemplate.getConverter()).setTypeMapper(new DefaultMongoTypeMapper(null));//removes _class
return mongoTemplate;
}
我在这个问题上挣扎了很长时间。我遵循了 Mkyong 但是当我介绍一个 LocalDate
属性(Java 8的任何JSR310类)我收到以下例外:
org.springframework.core.convert.ConverterNotFoundException:
No converter found capable of converting from type [java.time.LocalDate] to type [java.util.Date]
相应的转换器 org.springframework.format.datetime.standard.DateTimeConverters
是弹簧4.1的一部分,在弹簧数据mongodb 1.7中引用。即使我使用了新版本,转换器也没有跳入。
解决方案是使用现有的 MappingMongoConverter
而且只提供新的 DefaultMongoTypeMapper
(Mkyong的代码正在评论):
@Configuration
@EnableMongoRepositories
class BatchInfrastructureConfig extends AbstractMongoConfiguration
{
@Override
protected String getDatabaseName() {
return "yourdb"
}
@Override
Mongo mongo() throws Exception {
new Mongo()
}
@Bean MongoTemplate mongoTemplate()
{
// overwrite type mapper to get rid of the _class column
// get the converter from the base class instead of creating it
// def converter = new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext())
def converter = mappingMongoConverter()
converter.typeMapper = new DefaultMongoTypeMapper(null)
// create & return template
new MongoTemplate(mongoDbFactory(), converter)
}
总结:
- 延长
AbstractMongoConfiguration
- 注释
EnableMongoRepositories
- 在
mongoTemplate
从基类获取转换器,这可以确保注册类型转换类
您只需要将@Typealias注释添加到“更改类型映射器”的类省
@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;
}
}