Spring 数据 Mongo - 继承和可嵌入
Spring Data Mongo - Inheritance and Embeddable
假设我有一个 Customer
实体,其列表为 Vehicles
:
@Document
public class Customer {
private List<Vehicle> vehicles;
//... getters, setters
}
Vehicle
是一个抽象 class 有几个子类型:
public abstract class Vehicle {
}
@TypeAlias("CAR")
public class Car {
}
@TypeAlias("BOAT")
public class Boat {
}
@TypeAlias("MOTORBIKE")
public class Motorbike {
}
有什么方法可以让 Spring 处理这个用例吗?即,如果我针对客户保存 Car
和 Boat
,请问他们在查询 Customer
时是否正确补水?目前,我得到一个 java.lang.InstantiationError
作为 Spring 数据似乎正在尝试创建 Vehicle
抽象 class.
的实例
已成功解决问题。
基本上,我需要将包含 Vehicle
classes 的包添加到我的 Mongo 配置 class 中,如下所示:
public class CustomerDbConfig extends AbstractMongoConfiguration {
...
@Override
protected Collection<String> getMappingBasePackages() {
Collection<String> mappingBasePackages = new ArrayList<>();
mappingBasePackages.add(Vehicle.class.getPackageName());
return mappingBasePackages;
}
}
我认为以上内容在大多数情况下应该有效。我的理解是,如果 Configuration class 与 Vehicle
classes 在同一个包中,则上述内容可能不是必需的,但是,就我而言,它们在两个不同的包中。
此外,我这边有点复杂,因为我有多个 Mongo 数据库,配置不同,MongoTemplate
bean 也不同。
最初,我按如下方式创建 MongoTemplate
:
@Primary
@Bean(name = "customerMongoTemplate")
public MongoTemplate customerMongoTemplate() {
MongoTemplate mongoTemplate = new MongoTemplate(mongoClient(), getDatabaseName());
MappingMongoConverter converter = (MappingMongoConverter) mongoTemplate.getConverter();
converter.setCustomConversions(customConversions());
converter.afterPropertiesSet();
return mongoTemplate;
}
然而,通过 MongoTemplate
以这种方式获得 MappingMongoConverter
意味着 getMappingBasePackages
从未被调用。我试图通过执行以下操作来获取转换器:
@Primary
@Bean(name = "customerMongoTemplate")
public MongoTemplate customerMongoTemplate() {
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
}
但是它没有用,因为 mongoDbFactory()
和 mappingMongoConverter()
正在为不同的 MongoDB 配置返回 bean...这对我来说是理想的解决方案,但不确定如何让它在多个配置下可靠地工作 classes.
最后,我设法可靠地工作如下:
@Primary
@Bean(name = "customerMongoTemplate")
public MongoTemplate customerMongoTemplate() throws Exception {
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient(), getDatabaseName());
MongoMappingContext mongoMappingContext = mongoMappingContext();
mongoMappingContext.setInitialEntitySet(getInitialEntitySet());
mongoMappingContext.afterPropertiesSet();
MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), mongoMappingContext);
converter.setCustomConversions(customConversions());
converter.afterPropertiesSet();
return new MongoTemplate(mongoDbFactory, converter);
}
我对上述方法不是很满意,它有点挑剔,可能会导致新版本 Spring 出现问题,但是,它确实有效。
假设我有一个 Customer
实体,其列表为 Vehicles
:
@Document
public class Customer {
private List<Vehicle> vehicles;
//... getters, setters
}
Vehicle
是一个抽象 class 有几个子类型:
public abstract class Vehicle {
}
@TypeAlias("CAR")
public class Car {
}
@TypeAlias("BOAT")
public class Boat {
}
@TypeAlias("MOTORBIKE")
public class Motorbike {
}
有什么方法可以让 Spring 处理这个用例吗?即,如果我针对客户保存 Car
和 Boat
,请问他们在查询 Customer
时是否正确补水?目前,我得到一个 java.lang.InstantiationError
作为 Spring 数据似乎正在尝试创建 Vehicle
抽象 class.
已成功解决问题。
基本上,我需要将包含 Vehicle
classes 的包添加到我的 Mongo 配置 class 中,如下所示:
public class CustomerDbConfig extends AbstractMongoConfiguration {
...
@Override
protected Collection<String> getMappingBasePackages() {
Collection<String> mappingBasePackages = new ArrayList<>();
mappingBasePackages.add(Vehicle.class.getPackageName());
return mappingBasePackages;
}
}
我认为以上内容在大多数情况下应该有效。我的理解是,如果 Configuration class 与 Vehicle
classes 在同一个包中,则上述内容可能不是必需的,但是,就我而言,它们在两个不同的包中。
此外,我这边有点复杂,因为我有多个 Mongo 数据库,配置不同,MongoTemplate
bean 也不同。
最初,我按如下方式创建 MongoTemplate
:
@Primary
@Bean(name = "customerMongoTemplate")
public MongoTemplate customerMongoTemplate() {
MongoTemplate mongoTemplate = new MongoTemplate(mongoClient(), getDatabaseName());
MappingMongoConverter converter = (MappingMongoConverter) mongoTemplate.getConverter();
converter.setCustomConversions(customConversions());
converter.afterPropertiesSet();
return mongoTemplate;
}
然而,通过 MongoTemplate
以这种方式获得 MappingMongoConverter
意味着 getMappingBasePackages
从未被调用。我试图通过执行以下操作来获取转换器:
@Primary
@Bean(name = "customerMongoTemplate")
public MongoTemplate customerMongoTemplate() {
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
}
但是它没有用,因为 mongoDbFactory()
和 mappingMongoConverter()
正在为不同的 MongoDB 配置返回 bean...这对我来说是理想的解决方案,但不确定如何让它在多个配置下可靠地工作 classes.
最后,我设法可靠地工作如下:
@Primary
@Bean(name = "customerMongoTemplate")
public MongoTemplate customerMongoTemplate() throws Exception {
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient(), getDatabaseName());
MongoMappingContext mongoMappingContext = mongoMappingContext();
mongoMappingContext.setInitialEntitySet(getInitialEntitySet());
mongoMappingContext.afterPropertiesSet();
MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), mongoMappingContext);
converter.setCustomConversions(customConversions());
converter.afterPropertiesSet();
return new MongoTemplate(mongoDbFactory, converter);
}
我对上述方法不是很满意,它有点挑剔,可能会导致新版本 Spring 出现问题,但是,它确实有效。