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 处理这个用例吗?即,如果我针对客户保存 CarBoat,请问他们在查询 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 出现问题,但是,它确实有效。