[英]No qualifying bean of type '....mongodb.core.convert.MappingMongoConverter' available when doing multiple mongo on Spring Boot 2.2.x
[英]How to use Mongo Auditing and a UUID as id with Spring Boot 2.2.x?
我希望使用 UUID id 和 createdAt / updatedAt 字段存储文档。 我的解决方案是使用 Spring Boot 2.1.x。 从 Spring Boot 2.1.11.RELEASE 升级到 2.2.0.RELEASE 后,我对 MongoAuditing 的测试失败了, createdAt createdAt = null
。 我需要做什么才能再次填充 createdAt 字段?
这不仅仅是一个测试问题。 我运行了该应用程序,它的行为与我的测试相同。 所有审计字段保持为空。
我有一个配置来启用 MongoAuditing 和 UUID 生成:
@Configuration
@EnableMongoAuditing
public class MongoConfiguration {
@Bean
public GenerateUUIDListener generateUUIDListener() {
return new GenerateUUIDListener();
}
}
侦听器连接到onBeforeConvert
- 我想这就是麻烦开始的地方。
public class GenerateUUIDListener extends AbstractMongoEventListener<IdentifiableEntity> {
@Override
public void onBeforeConvert(BeforeConvertEvent<IdentifiableEntity> event) {
IdentifiableEntity entity = event.getSource();
if (entity.isNew()) {
entity.setId(UUID.randomUUID());
}
}
}
文档本身(我删除了 getter 和 setter):
@Document
public class MyDocument extends InsertableEntity {
private String name;
}
public abstract class InsertableEntity extends IdentifiableEntity {
@CreatedDate
@JsonIgnore
private Instant createdAt;
}
public abstract class IdentifiableEntity implements Persistable<UUID> {
@Id
private UUID id;
@JsonIgnore
public boolean isNew() {
return getId() == null;
}
}
一个完整的最小示例可以在这里找到(包括测试) https://github.com/mab/auditable使用 2.1.11.RELEASE 测试成功,2.2.0.RELEASE 失败。
对我来说,最好的解决方案是从事件 UUID 生成切换到基于回调的生成。 通过Ordered
的实现,我们可以设置在AuditingEntityCallback
之后执行的新回调。
public class IdEntityCallback implements BeforeConvertCallback<IdentifiableEntity>, Ordered {
@Override
public IdentifiableEntity onBeforeConvert(IdentifiableEntity entity, String collection) {
if (entity.isNew()) {
entity.setId(UUID.randomUUID());
}
return entity;
}
@Override
public int getOrder() {
return 101;
}
}
我使用MongoConfiguration
注册了回调。 对于更通用的解决方案,您可能需要查看AuditingEntityCallback
与`MongoAuditingBeanDefinitionParser 的注册。
@Configuration
@EnableMongoAuditing
public class MongoConfiguration {
@Bean
public IdEntityCallback registerCallback() {
return new IdEntityCallback();
}
}
MongoTemplate
在doInsert()
上的工作方式如下
this.maybeEmitEvent
- 发出一个事件( onBeforeConvert
、 onBeforeSave
等),因此任何AbstractMappingEventListener
都可以像使用GenerateUUIDListener
一样捕获并采取行动this.maybeCallBeforeConvert
- 在转换回调之前调用,比如mongo auditing
就像你在MongoTemplate.class
src (831-832) 的源代码中看到的一样
protected <T> T doInsert(String collectionName, T objectToSave, MongoWriter<T> writer) {
BeforeConvertEvent<T> event = new BeforeConvertEvent(objectToSave, collectionName);
T toConvert = ((BeforeConvertEvent)this.maybeEmitEvent(event)).getSource(); //emit event
toConvert = this.maybeCallBeforeConvert(toConvert, collectionName); //call some before convert handlers
...
}
MongoAudit
标记createdAt
仅通过检查以新的实体,如果entity.isNew() == true
因为您的代码 (UUID) 已经设置了未填充createdAt
的Id
(该实体不被视为新的)
您可以执行以下操作(按最佳到最差排序):
UUID
并使用String
作为您的 id,让 mongo 本身创建和管理它的实体 id(这就是MongoTemplate
实际工作的方式第 811-812 行)UUID
保留在代码级别,在从数据库插入和检索时从/转换为String
2.1.11.RELEASE
GenerateUUIDListener
以及id
设置updateAt
(重命名NewEntityListener
或smth),基本上实现审计isNew()
逻辑,它不仅仅依赖于实体id
在
2.1.11.RELEASE
版本中,方法的顺序被翻转(MongoTemplate.class
804-805)所以你的代码工作正常
作为一个抽象的方法,事件的性质是要排序的发送和忘记(异步兼容),所以这是一个非常不好的做法,改变物体本身,没有专营公司计算的顺序,如果有的话
这就是为什么审计建立在回调而不是事件上,这就是为什么 Pivotal 不(需要)保持版本之间的顺序
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.