【问题标题】:Spring Data Mongo - Inheritance and EmbeddableSpring Data Mongo - 继承和可嵌入
【发布时间】:2019-12-08 10:24:50
【问题描述】:

假设我有一个Customer 实体,其列表为Vehicles

@Document
public class Customer {
  private List<Vehicle> vehicles;

  //... getters, setters
} 

Vehicle 是一个带有几个子类型的抽象类:

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 Data 似乎正在尝试创建 Vehicle 抽象类的实例。

【问题讨论】:

    标签: java mongodb spring-boot spring-data spring-data-mongodb


    【解决方案1】:

    设法解决了问题。

    基本上,我需要将包含 Vehicle 类的包添加到我的 Mongo 配置类中,如下所示:

    public class CustomerDbConfig extends AbstractMongoConfiguration {
    
      ... 
    
      @Override
      protected Collection<String> getMappingBasePackages() {
        Collection<String> mappingBasePackages = new ArrayList<>();
        mappingBasePackages.add(Vehicle.class.getPackageName());
    
        return mappingBasePackages;
      }
    
    }
    

    我认为上述方法在大多数情况下都应该有效。我的理解是,如果 Configuration 类与 Vehicle 类在同一个包中,则可能不需要上述内容,但是,就我而言,它们位于两个不同的包中。

    此外,对我来说这有点复杂,因为我有多个配置不同的 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...这对我来说是理想的解决方案,但不知道如何让它可靠地与多个配置类。

    最后,我设法可靠地工作如下:

    @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 出现问题,但它确实有效。

    【讨论】:

    • 如果 springs 不管理类,一堆东西就不起作用。本教程展示了一种使用多个 Mongo DB 实例的看似干净的方法 - 在包级别分离实体。似乎更像春天的方式 - blog.marcosbarbero.com/…
    • 我正在我的代码库中做与该教程类似的事情,尽管我的用例有点复杂,因为我需要自定义转换器和包扫描类型别名。但是,就我而言,我的 Spring 正在管理 MongoTemplate?你认为哪个部分会崩溃?是否可以通过将MongoDbFactoryMappingMongoConverter 创建为单独的bean 而不是在创建MongoTemplate bean 的方法中创建它们来解决?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 2010-10-29
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 2014-05-15
    相关资源
    最近更新 更多