繁体   English   中英

为什么 Spring Data MongoDB 不公开更新…(…) 方法的事件?

[英]Why does Spring Data MongoDB not expose events for update…(…) methods?

似乎mongoOperations的更新不会触发AbstractMongoEventListener 中的事件。

这篇文章表明至少在 2014 年 11 月是这样

目前有没有办法监听如下更新事件? 如果是这样的话,这似乎是一个很大的遗漏。

MongoTemplate.updateMulti()

谢谢!

这不是疏忽。 事件至少围绕域对象或文档的生命周期设计,这意味着它们通常包含您感兴趣的域对象的实例。

另一方面,更新完全在数据库中处理。 所以在MongoTemplate中没有处理文档甚至域对象。 考虑这基本上与 JPA @EntityListener s 仅针对首先加载到持久性上下文中的实体触发的方式相同,但不会在执行查询时触发,因为在数据库中执行查询。

我知道现在回答这个问题为时已晚,我对MongoTemplate.findAndModify方法有同样的情况,我需要事件的原因是为了审计目的。 这是我所做的。

1.EventPublisher(这是MongoTemplate的方法)

public class CustomMongoTemplate extends MongoTemplate {

    private ApplicationEventPublisher applicationEventPublisher;


    @Autowired
    public void setApplicationEventPublisher(ApplicationEventPublisher
                                                         applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

   //Default Constructor here

    @Override
    public <T> T findAndModify(Query query, Update update, Class<T> entityClass) {
        T result = super.findAndModify(query, update, entityClass);

        //Publishing Custom Event on findAndModify
        if(result!=null && result instanceof Parent)//All of my Domain class extends Parent
            this.applicationEventPublisher.publishEvent(new AfterFindAndModify
                    (this,((Parent)result).getId(),
                            result.getClass().toString())
            );

        return result;
    } }

2.应用事件

public class AfterFindAndModify extends ApplicationEvent {

    private DocumentAuditLog documentAuditLog;

    public AfterFindAndModify(Object source, String documentId,
                            String documentObject) {
        super(source);
        this.documentAuditLog = new DocumentAuditLog(documentId,
                documentObject,new Date(),"UPDATE");
    }

    public DocumentAuditLog getDocumentAuditLog() {
        return documentAuditLog;
    }
}

3.应用监听器

public class FindandUpdateMongoEventListner implements ApplicationListener<AfterFindAndModify> {

    @Autowired
    MongoOperations mongoOperations;

    @Override
    public void onApplicationEvent(AfterFindAndModify event) {
        mongoOperations.save(event.getDocumentAuditLog());
    }
}

进而

@Configuration
@EnableMongoRepositories(basePackages = "my.pkg")
@ComponentScan(basePackages = {"my.pkg"})
public class MongoConfig extends AbstractMongoConfiguration {

    //.....

    @Bean
    public FindandUpdateMongoEventListner findandUpdateMongoEventListner(){
        return new FindandUpdateMongoEventListner();
    }   

}

您可以监听数据库更改,甚至是完全在程序之外的更改(MongoDB 4.2 和更新版本)。

(代码使用kotlin语言。Java相同)

@Autowired private lateinit var op: MongoTemplate

@PostConstruct
fun listenOnExternalChanges() {
    Thread {
        op.getCollection("Item").watch().onEach {
            if(it.updateDescription.updatedFields.containsKey("name")) {
                println("name changed on a document: ${it.updateDescription.updatedFields["name"]}")
            }
        }
    }.start()
}

此代码仅在启用复制时有效。 即使只有一个节点,您也可以启用它:

将以下副本集详细信息添加到 mongodb.conf(/etc/mongodb.conf 或 /usr/local/etc/mongod.conf 或 C:\\Program Files\\MongoDB\\Server\\4.0\\bin\\mongod.cfg)文件

replication:
  replSetName: "local"

重启 mongo 服务,然后打开 mongo 控制台并运行以下命令:

rs.initiate()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM