`
iamlotus
  • 浏览: 109304 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

如何自动备份删除的对象(3)

阅读更多

到目前为止我们有了一套从Object自动生成Map<String,Object>的工具,下面要作的就是把这个Map中的信息给持久化了,依照不同的持久化方式和后继对删除对象的查询方式,这又有着不同的solution。比如持久化到文件系统和数据库,显然要用不同的方式。

目前这个系统采用的是数据库,OR-Mapping用的是Toplink。对于删除的数据,在前台有能够查询的界面,可供业务人员查询。针对这样的需求,需要解决以下的几个问题。

首先,在何处获得被删除的对象?BaseDao.deleteObject(Object obj)似乎是一个不错的入口,可惜的是,Toplink对于private owner的对象会自动删除,而service developer不会向下面这样去删除一个对象

 

//如果想在BaseDao.deleteObject(obj)中捕获删除对象,
//那就要求service这样去删除一个具有private owner 属性的Order

for (Item item: order.getItems()){
    getBaseDao().deleteObject(item);
}

getBaseDao().deleteObject(order);

 

所以,为了透明地得到所有Toplink实际删除了的对象,要在每个UnitOfWork生成时要注册一个Toplink的SessionEventListener

 

import java.util.Date;
import java.util.Enumeration;
import java.util.Map;

import oracle.toplink.internal.helper.IdentityHashtable;
import oracle.toplink.publicinterface.UnitOfWork;
import oracle.toplink.sessions.SessionEvent;
import oracle.toplink.sessions.SessionEventAdapter;


public class RecordListener extends SessionEventAdapter {
    protected static final FWIIntegrator integrator = FWIntegratorFactory.getIntegrator();

    @Override
    public void postCommitUnitOfWork(SessionEvent event) {
        try {
            UnitOfWork unitOfWork = (UnitOfWork) event.getSession();
            UnitOfWork uow4DeletionRecord = null;
            IdentityHashtable objectsDeletedDuringCommit = unitOfWork.getObjectsDeletedDuringCommit();
            for (Enumeration<?> e = objectsDeletedDuringCommit.keys(); e.hasMoreElements();) {
                Object key = e.nextElement();
                RecordUtils recordUtils = RecordUtils.instance();
                Map<String, Object> content = recordUtils.toContent(key);
                if (content != null) {
                    // since deleted objects are detected in post commit callback
                    // we have to acquire another UOW to write DeletionRecord
                    if (uow4DeletionRecord == null) {
                        uow4DeletionRecord = ParamUtils.getDataSource().getSession().acquireUnitOfWork();
                    }

                    DeletionRecord deleteRecord = recordUtils.toDeleteRecord(content);
                    deleteRecord.setOperatingTime(new Date());
                    uow4DeletionRecord.assignSequenceNumber(deleteRecord);
                    uow4DeletionRecord.registerNewObject(deleteRecord);
                }

            }

            if (uow4DeletionRecord != null) {
                uow4DeletionRecord.commit();
                uow4DeletionRecord.release();
            }
        } catch (Exception e) {
           // You may log it by yourself
        }
    }
}
 
    private void initSessionAndUnitOfWork(ServerSession serverSession) {
        clientSession = serverSession.acquireClientSession();
        uw = clientSession.acquireUnitOfWork();
        addListenerToUnitOfWork(uw);
    }

    private void addListenerToUnitOfWork(UnitOfWork uw) {
        uw.getEventManager().addListener(new RecordListener());
    }
 

   这个Listener的作用时间是postCommitUnitOfWork,目的是保证UnitOfWork.getObjectsDeletedDuringCommit()有值。当然,由于原有的UnitOfWork已经commit了,所以得新起一个UnitOfWork来写这些DeletionRecord对象

 

  DeletionRecord没有什么特别的东西,它包含一些查询所用到的warehouse,owner,location之类的业务字段(这些字段在数据库中会作索引,同时含有一个content字段,其中存储的是从那个Map转换过来的XML

public class DeletionRecord extends OidEnabledComponent {

    private static interface DeletionRecordSetterCallback {
        void setValue(DeletionRecord obj, Object value);
    }

    public static enum FieldType {

        CLASS_NAME(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setClassName((String) value);
            }
        }),

        WAREHOUSE_ID(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setWarehouseId((String) value);
            }

        }), OWNER_ID(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setOwnerId((String) value);
            }

        }), LOCATION_ID(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setLocationId((String) value);
            }

        }), ITEM_NO(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setItemNo((String) value);
            }

        }), ITEM_DESCRIPTION(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setItemDescription((String) value);
            }

        }), BIZ_TYPE(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setBizType((Long) value);
            }

        }), ASN_NO(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setAsnNo((String) value);
            }

        }), RECEIVE_DATE(new DeletionRecordSetterCallback() {
            public void setValue(DeletionRecord obj, Object value) {
                obj.setReceiveDate((Date) value);
            }

        });
        private DeletionRecordSetterCallback setterCallback;

        FieldType(DeletionRecordSetterCallback setterCallback) {
            this.setterCallback = setterCallback;
        };

        public void setValue(DeletionRecord obj, Object value) {
            this.setterCallback.setValue(obj, value);
        }

    }

    private String className;

    private String warehouseId;

    private String ownerId;

    private String locationId;

    private String itemNo;

    private String itemDescription;

    private Long bizType;

    private String asnNo;

    private Date receiveDate;

    private String operatorId;

    private Date operatingTime;

    private String content;

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getWarehouseId() {
        return warehouseId;
    }

    public void setWarehouseId(String warehouseId) {
        this.warehouseId = warehouseId;
    }

    public String getOwnerId() {
        return ownerId;
    }

    public void setOwnerId(String ownerId) {
        this.ownerId = ownerId;
    }

    public String getLocationId() {
        return locationId;
    }

    public void setLocationId(String locationId) {
        this.locationId = locationId;
    }

    public String getItemNo() {
        return itemNo;
    }

    public void setItemNo(String id) {
        this.itemNo = id;
    }

    public String getItemDescription() {
        return itemDescription;
    }

    public void setItemDescription(String name) {
        this.itemDescription = name;
    }

    public Long getBizType() {
        return bizType;
    }

    public void setBizType(Long bizType) {
        this.bizType = bizType;
    }

    public String getAsnNo() {
        return asnNo;
    }

    public void setAsnNo(String asnNo) {
        this.asnNo = asnNo;
    }

    public Date getReceiveDate() {
        return receiveDate;
    }

    public void setReceiveDate(Date receiveDate) {
        this.receiveDate = receiveDate;
    }

    public String getOperatorId() {
        return operatorId;
    }

    public void setOperatorId(String operatorId) {
        this.operatorId = operatorId;
    }

    public Date getOperatingTime() {
        return operatingTime;
    }

    public void setOperatingTime(Date operatingTime) {
        this.operatingTime = operatingTime;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

}
 

   需要注意的是,这个转换出来的deletionRecord不是在原有的UnitOfWork中写入的,所以那一段专门去catch了Exception。这是基于以下想法:即使自动备份失败了,也不应该影响正常的删除逻辑。如果认为自动备份失败就不能继续往下作的话,这个catch是要去掉的。

 

   至此,一个自动备份删除对象的简易框架就搭好了。总结一下,核心思想包括以下几点

  1)通过Annotation和interface,使得一个对象能够在被删除时指出自己的哪些信息需要被记录

  2)通过SessionEventListen得到所有被删除的对象,保持对使用者的透明

  3)把结果信息分为两部分,需要查询的用单独的字段记录做索引,其余信息用一个单层的XML保存。

 

 

 

再深入考虑的话,这个框架可以有以下的改进:

一是用XML指定要删除的对象和属性,作到对原始文件的完全无侵入;二是持久化到数据库外其他的媒介如文件系统、网络等,这就可以抽象出一个Appender interface,再实现FileAppender, DBApplender等对象;最后如果性能有需要,可以把持久化被删除对象和删除业务对象的逻辑做成异步的,这样删除N个对象后才持久化一次删除动作,能够减少业务逻辑的延迟。

 

 

 

0
0
分享到:
评论

相关推荐

    sql2008自动备份数据库和定期删除数据库备份

    SQLServer 2008 自动备份数据库和定期删除数据库备份 SQLServer 2008 通过创建维护计划可以实现自动备份数据库和定期删除备份。为了实现这个功能,必须开启 SQLServer 的 SQLServer Agent 服务,因为这个服务默认是...

    在SQL Server 2005数据库中实现自动备份自动删除备份文件

    在SQL Server 2005中,为了确保数据的安全性和可恢复性,自动备份和自动删除备份文件是非常关键的操作。以下是如何在SQL Server 2005中实现这两个功能的详细步骤: 一、创建自动备份 1. **打开SQL Server ...

    sql自动备份(如何自动备份)

    在SQL Server中,数据库的自动备份是确保数据安全和防止数据丢失的重要措施。本文将详细介绍如何设置SQL Server的自动定时备份功能,以便在无需人工干预的情况下定期执行备份任务。 首先,确保您的计算机已经安装了...

    windows下oracle11g数据泵自动备份脚本

    windows下oracle11g数据泵自动备份脚本含删除过期备份和使用方法 1、先建备份用的路径对象:(注:此处认为用来做备份的用户backupuser已经建好了,且已经有连接数据库的相应权限) sqlplus / as sysdba CREATE OR ...

    pb 12.5编写自动备份工具

    3. **计划任务**:为了实现定时自动备份,工具可能使用了Windows操作系统自带的“任务计划程序”服务,创建一个定时任务来调用备份程序。也可以通过PB内部的事件调度机制来实现,比如设置一个定时器触发备份操作。 ...

    自动备份和按日期删除程序

    在IT领域,自动备份和按日期删除程序是保持数据安全和系统整洁的重要工具。VBScript(Visual Basic Script)是一种轻量级的脚本语言,常用于Windows系统的自动化任务,如批处理、网页交互等。本程序就是利用VBScript...

    oracle自动备份工具

    RMAN还能进行验证备份、删除旧备份和执行自动备份策略。 2. **自动备份策略**:在Oracle中,可以通过RMAN配置自动备份策略,例如设置每天或每周的特定时间执行备份,以及指定备份存储位置。这可以通过RMAN的`RUN`块...

    oracle数据库自动备份

    "Oracle数据库自动备份"指的是利用Oracle提供的工具和策略,设定定期自动执行数据库备份,以确保数据的安全性。 Oracle数据库提供了多种备份方式,包括物理备份和逻辑备份。物理备份主要是通过RMAN(恢复管理器)...

    oracle自动备份脚本的

    在IT行业中,数据库的备份是至关重要的,尤其是对于企业级应用来说,Oracle数据库的自动备份是确保数据安全的重要环节。本文将围绕“Oracle自动备份脚本”这一主题,详细讲解如何利用脚本来实现Oracle数据库的定时...

    sql2008自动备份

    本篇文章将深入探讨如何在SQL Server 2008中设置自动备份,这对于数据库管理员以及对数据库操作有一定了解的初学者来说,是一项基础但关键的操作。 首先,我们从【描述】中了解到,SQL Server Management Studio...

    使用PB9做的sqlserver数据库的自动备份软件

    标题中的“使用PB9做的sqlserver数据库的自动备份软件”指的是使用PowerBuilder 9(简称PB9)开发的一款工具,该工具专为SQL Server数据库设计,目的是实现数据库的自动化备份。PowerBuilder是一款强大的可视化编程...

    excel对象清理工具/vba清理Excel对象

    excel多余对象清理工具/...删除多余对象前自动备份文件 目前删除几万个还是OK的(测试3-4万个对象处理需要2分钟左右),几十万个就另外手工处理吧,直接卡死。 还有很多不足,还有很多需要改善的地方,请大佬指点指点~

    Oracle数据库对象管理及备份与恢复.pdf

    Oracle数据库是业界广泛使用的大型关系型数据库系统,其对象管理及备份与恢复机制对于数据库管理员来说至关重要。本文将详细介绍Oracle数据库的对象管理、数据类型、触发器、索引和分区策略,以及备份与恢复的相关...

    PB实现sql数据库自动备份

    本文将详细阐述如何使用PowerBuilder(PB)实现SQL数据库的自动备份,以及涉及的相关知识点,包括数据恢复、特殊数据处理和数据上传下载。 一、SQL数据库自动备份 SQL数据库自动备份是为了防止数据丢失或系统故障...

    java自动备份

    Java自动备份系统是一种高效、可靠的解决方案,用于在服务器上实现资源文件的自动化上传、下载以及备份功能。这个系统的核心在于利用Java编程语言的强大能力和灵活性,结合相关库和框架,实现文件管理的自动化流程,...

    文件夹自动备份工具+vb源代码

    本文将围绕一款名为“文件夹自动备份工具+vb源代码”的工具进行讨论,它不仅提供了可执行的备份程序FolderBackup.exe,还附带了详细的VB源代码,让使用者能够根据自己的需求调整并学习到如何开发类似的工具。...

    SQL2008设置自动备份与删除.doc

    ### SQL Server 2008 自动备份与删除策略详解 #### 一、背景与目的 随着业务数据量的增长及重要性的提升,确保数据库的安全性和稳定性成为IT部门的一项重要职责。在SQL Server 2008中,为了保护数据安全并提供有效...

    Oracle数据库定时自动备份批处理代码(Windows)

    Oracle数据库定时自动备份对于保障数据安全至关重要,尤其是在Windows环境下,通过批处理脚本可以实现这一功能。以下是一个详细的Oracle数据库定时自动备份的步骤和相关知识点: 1. **批处理脚本**: - `...

    wxh PB数据库自动备份软件

    PB数据库自动备份软件是一款专为PowerBuilder(简称PB)数据库设计的工具,旨在简化数据库的备份过程,确保数据的安全性和完整性。PowerBuilder是一款强大的数据库应用开发环境,它使用DataWindow控件来处理数据库...

Global site tag (gtag.js) - Google Analytics