在保存、更新和删除时发出事件的 DAO

Posted

技术标签:

【中文标题】在保存、更新和删除时发出事件的 DAO【英文标题】:DAO that emit events on save, update and delete 【发布时间】:2013-03-24 18:33:43 【问题描述】:

我创建了几个 DAO 类(我正在使用 Spring JDBC),我想在保存、更新和删除时发出事件,以便我也可以更新搜索索引。

一种方法是在每个 DAO 中创建事件发出逻辑,但这将是很多重复。所以我想到了使用 AOP 和“周围的建议”,但我不知道这是否是使用 AOP 的正确“时间”。还有其他更合适的解决方案吗?

【问题讨论】:

【参考方案1】:

您也可以通过使用侦听器来做到这一点。流程有点反转,因为子类利用父类作为各种帮助。

public abstract class AbstractCrudDao<T> 
    private Collection<Listener> listeners = new HashSet<Listener>();

    public void addListener(final Listener listener) 
        listeners.add(listener);
    

    protected void doAction(CrudAction<T> crudAction)
    
        for(Listener listener : listeners) 
             listener.beforeAction();
        
        crudAction.doAction();
        for(Listener listener : listeners) 
             listener.afterAction();
        
    

    public interface CrudAction 
        void doAction();
    

    public interface Listener 
        void beforeAction();
        void afterAction();
    


public class CarDao extends AbstractCrudDao 
    public void create(Car car) 
        doAction(new CrudAction() 
            public void doAction() 
                //create car here
            
        );
    

您可以为每个 CRUD 操作创建一个单独的 CollectionListener,或者根据您的喜好随意更改。

【讨论】:

感谢更新,但是如何在子类中指定 create 方法的实现呢?比如车道?如果您在抽象 dao 中指定所有内容,我会看到这是如何工作的,但不是当您需要在子类中实现实际逻辑时 这当然看起来更像我需要的,谢谢!并不是说您的回调示例也很糟糕,但我正在考虑灵活性和 API 设计。但是,例如,您如何只调用 InsertListeners 或 UpdateListeners 呢?您是否创建不同版本的 CrudAction 并使用 instanceof 运算符? 我的意思是,当我插入内容时,我只想通知插入侦听器,更新时仅更新侦听器,删除时仅删除侦听器。 我真的不想为你做这整件事。你认为你可以尝试以此为例吗?您如何发布一个新问题,说明您遇到的问题?【参考方案2】:

我会通过为所有 CRUD dao 创建一个抽象基类来做到这一点。基本接口将采用某种回调机制,看起来像这样:

public abstract class AbstractCrudDao<T> 
    public void create(T t, CompleteCallback completeCallback)
    
        create(t);
        completeCallback.onComplete();
    

    public abstract void create(T t);

    //same for read, update, delete

    public interface CompleteCallback 
        void onComplete();
    

显然,这是一个远非完整的示例,但我认为它展示了利用回调作为完成触发器的想法。您也可以进一步扩展接口以接收 onException 事件。

如果您使用 Spring 的事务管理,您可能需要根据您是否希望回调事件发生在事务内部或外部进行一些进一步的调整。

就我个人而言,除非您不拥有 DAO 代码,否则我不会为此使用 AOP,但即使是这种情况,也可能会首选其他一些机制。

【讨论】:

我可以看到这是如何工作的,但是我有一个关于用法的问题。您会在索引对象的服务中实现回调侦听器,还是会创建一个实现接口的匿名类,然后在其中使用搜索索引器? 嗯,这取决于谁将对回调采取行动。您可能需要将回调(通过回调的委托)传播到适当的位置。此时,您可以使用匿名内部类或***具体实现来内联实现。 很好,我会尝试实现这一点。喜欢它的想法:) 我试图让它与听众一起工作。我已经删除了回调参数。你知道它是怎么做到的吗? 我有一个 create 方法,我想在操作前通知所有侦听器,然后运行 ​​create 方法,然后在操作后运行所有侦听器。

以上是关于在保存、更新和删除时发出事件的 DAO的主要内容,如果未能解决你的问题,请参考以下文章

架构模式: 领域事件

CKEditor 5如何从任何小部件/模型/视图中获取单击,更新和删除的事件

Flux:处理模态窗口

Nopcommerce 之事件机制

Vue.js - 如何在数据对象更改时向父组件发出?

MS Access DAO 连接在退出时放弃更改