Couldn't find PersistentEntity for type class when using @EnableMongoAuditing

旧时模样 提交于 2020-12-05 05:44:44

问题


I am getting "Couldn't find PersistentEntity for type class" error when I am using @EnableMongoAuditing features along with MongoRepository. This happens when I save a document when collection isn't already present in database.

I tried whatever is mentioned in:

  • https://github.com/spring-projects/spring-boot/issues/12023
  • https://jira.spring.io/browse/DATAMONGO-1999
  • Spring boot mongodb auditing error

but nothing is working.

Mentioned things are:

Extend MongoConfig by AbstractMongoConfiguration and override all methods.

Here is my code which reproduced the same error:

MongoConfig class

@Configuration
public class MongoConfig extends AbstractMongoConfiguration {

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

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

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

    @Override
    public MongoDbFactory mongoDbFactory() {
        return new SimpleMongoDbFactory(new MongoClient(mongoHost + ":" + mongoPort), mongoDB);
    }

    @Override
    public MongoClient mongoClient() {
        return new MongoClient(mongoHost, Integer.parseInt(mongoPort));
    }

    @Override
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoDbFactory());
    }

    @Override
    public MappingMongoConverter mappingMongoConverter() {
        return new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()), new MongoMappingContext());
    }

    @Override
    protected String getDatabaseName() {
        return mongoDB;
    }
}

Person Collection class

@Document
public class Person {
    @Id
    private String id;

    private String name;

    @CreatedDate
    private LocalDateTime createdAt;
    @LastModifiedDate
    private LocalDateTime lastModified;
    // Getter Setters Constructors omitted for brevity
}

Main Application class

@EnableMongoAuditing
@EnableMongoRepositories ({"com.example.*", "org.apache.*"})
@SpringBootApplication
@ComponentScan({"com.example.*", "org.apache.*"})
public class DemoApplication implements CommandLineRunner {

    @Autowired
    PersonRepository personRepository;
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        Person p1 = new Person("1", "prakhar");
        personRepository.save(p1);

    }
}

Expected Result is Person entity should be saved in database. Actual Result is "Couldn't find PersistentEntity for type class Person" error


回答1:


Looks like you ran into https://github.com/spring-projects/spring-boot/issues/12023

Extending AbstractMongoConfiguration will switch off Spring Boot's auto-configuration of various Mongo components and also customises the base packages that are used to scan for mappings. I would recommend that you don't use it in Spring Boot.

Update

I managed to get the example running with the configuration as simple as

@Configuration
public class MongoConfig {

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

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

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

    @Bean
    public MongoDbFactory mongoDbFactory() {
        return new SimpleMongoDbFactory(new MongoClient(mongoHost + ":" + mongoPort), mongoDB);
    }

    @Bean
    public MongoClient mongoClient() {
        return new MongoClient(mongoHost, Integer.parseInt(mongoPort));
    }
}

and the app class

@EnableMongoAuditing
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    PersonRepository personRepository;
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        Thread.sleep(2000);
        Person p1 = new Person("1", "prakhar");
        personRepository.save(p1);

    }
}

Notice that I followed my own advice and did't inherit from AbstractMongoConfiguration

Explaination

The problem lies in the initialization of

 @Bean
 public MappingMongoConverter mappingMongoConverter() {
     return new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()), new MongoMappingContext());
}

You simply call MongoMappingContext constructor, without calling setInitialEntitySet. Compare that with MongoDataConfiguration auto-configuration class.

@Bean
@ConditionalOnMissingBean
public MongoMappingContext mongoMappingContext(MongoCustomConversions conversions)
        throws ClassNotFoundException {
    MongoMappingContext context = new MongoMappingContext();
    context.setInitialEntitySet(new EntityScanner(this.applicationContext)
            .scan(Document.class, Persistent.class));
    Class<?> strategyClass = this.properties.getFieldNamingStrategy();
    if (strategyClass != null) {
        context.setFieldNamingStrategy(
                (FieldNamingStrategy) BeanUtils.instantiateClass(strategyClass));
    }
    context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
    return context;
}

Even worse, you don't register MongoMappingContext as a managed bean. Due to this fact, auto-configuration class is still created. This leads to a race condition, I tried to run the original code and could easily reproduce the error, but with a breakpoint in AbstractMappingContext.addPersistentEntity the test always passed.



来源:https://stackoverflow.com/questions/55915594/couldnt-find-persistententity-for-type-class-when-using-enablemongoauditing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!