使用@EnableMongoAuditing 时找不到类型 class 的 PersistentEntity
Couldn't find PersistentEntity for type class when using @EnableMongoAuditing
当我将 @EnableMongoAuditing
功能与 MongoRepository 一起使用时,出现“无法找到 class 类型的 PersistentEntity”错误。
当我在数据库中不存在集合时保存文档时会发生这种情况。
我尝试了以下提到的任何方法:
- https://github.com/spring-projects/spring-boot/issues/12023
- https://jira.spring.io/browse/DATAMONGO-1999
- Spring boot mongodb auditing error
但没有任何效果。
提到的东西是:
通过 AbstractMongoConfiguration 扩展 MongoConfig 并覆盖所有方法。
这是我的代码,它重现了同样的错误:
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;
}
}
人物合集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
}
主应用程序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);
}
}
预期结果是 Person 实体应该保存在数据库中。
实际结果是“找不到类型 class Person 的 PersistentEntity”错误
看起来你 运行 变成了 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.
更新
我设法得到了示例运行配置就像
一样简单
@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));
}
}
和应用程序 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);
}
}
请注意,我遵循了自己的建议,并没有继承自 AbstractMongoConfiguration
说明
问题出在初始化
@Bean
public MappingMongoConverter mappingMongoConverter() {
return new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()), new MongoMappingContext());
}
您只需调用 MongoMappingContext
构造函数,而不调用 setInitialEntitySet
。将其与 MongoDataConfiguration
自动配置 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;
}
更糟糕的是,您没有将 MongoMappingContext
注册为托管 bean。
由于这个事实,自动配置 class 仍然被创建。这导致了竞争条件,我尝试 运行 原始代码并且可以很容易地重现错误,但是在 AbstractMappingContext.addPersistentEntity
中有一个断点,测试总是通过。
对我来说,如果您的 class 从 AbstractMongoConfiguration
扩展,我通过在 MongoConfig
中添加以下方法解决了这个问题
@Override
protected String getMappingBasePackage() {
return "com.companyName.modulename"
}
如果 MongoConfig
从 MongoConfigurationSupport
扩展,则添加下面的方法
@Override
protected Collection<String> getMappingBasePackages() {
return Arrays.asList("com.companyName.module1","com.companyName.module2");
}
请注意,在以后的情况下,我可以将多个包名称指定为基础包。
当我将 @EnableMongoAuditing
功能与 MongoRepository 一起使用时,出现“无法找到 class 类型的 PersistentEntity”错误。
当我在数据库中不存在集合时保存文档时会发生这种情况。
我尝试了以下提到的任何方法:
- https://github.com/spring-projects/spring-boot/issues/12023
- https://jira.spring.io/browse/DATAMONGO-1999
- Spring boot mongodb auditing error
但没有任何效果。
提到的东西是:
通过 AbstractMongoConfiguration 扩展 MongoConfig 并覆盖所有方法。
这是我的代码,它重现了同样的错误:
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;
}
}
人物合集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
}
主应用程序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);
}
}
预期结果是 Person 实体应该保存在数据库中。 实际结果是“找不到类型 class Person 的 PersistentEntity”错误
看起来你 运行 变成了 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.
更新
我设法得到了示例运行配置就像
一样简单@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));
}
}
和应用程序 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);
}
}
请注意,我遵循了自己的建议,并没有继承自 AbstractMongoConfiguration
说明
问题出在初始化
@Bean
public MappingMongoConverter mappingMongoConverter() {
return new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()), new MongoMappingContext());
}
您只需调用 MongoMappingContext
构造函数,而不调用 setInitialEntitySet
。将其与 MongoDataConfiguration
自动配置 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;
}
更糟糕的是,您没有将 MongoMappingContext
注册为托管 bean。
由于这个事实,自动配置 class 仍然被创建。这导致了竞争条件,我尝试 运行 原始代码并且可以很容易地重现错误,但是在 AbstractMappingContext.addPersistentEntity
中有一个断点,测试总是通过。
对我来说,如果您的 class 从 AbstractMongoConfiguration
MongoConfig
中添加以下方法解决了这个问题
@Override
protected String getMappingBasePackage() {
return "com.companyName.modulename"
}
如果 MongoConfig
从 MongoConfigurationSupport
扩展,则添加下面的方法
@Override
protected Collection<String> getMappingBasePackages() {
return Arrays.asList("com.companyName.module1","com.companyName.module2");
}
请注意,在以后的情况下,我可以将多个包名称指定为基础包。