zoukankan      html  css  js  c++  java
  • hibernate监听器的应用

    这里是我看到的一个hibernate监听器的简单实现供参考  http://www.360doc.com/content/14/0623/11/8072791_389034447.shtml

    设计思路:

    首先,提供一个接口,我们监听实体变化其实需要的就是监听实体增删改的过程,这里我们提供的参数EntityImpl时我们系统业务类的顶层实现(相信我们每个公司的产品都会有一个顶层类),然后是一个记录操作日志的实体类History。

    1 public interface IHistoryListenerProcess {
    2     public void postInsert(EntityImpl operateObject,History history);
    3     public void preDelete(EntityImpl operateObject,History history);
    4     public void postUpdate(EntityImpl operateObject,History history);
    5 }

     这个history的参数并不全,相信每个系统也都各异,但是共有的方法还是有一些的

     1 public class History extends SysEntity {
     2 
     3     private static final long serialVersionUID = 6727254578815488286L;
     4 
     5     public static final String SEPERATOR = "⑧";
     6 
     7     private String dataId;
     8     @Meaning("操作人ID")
     9     private String operatorId;
    10     @Meaning("操作人名称")
    11     private String operatorName;
    12     @Meaning("操作时间")
    13     private Timestamp operateDate;
    14     @Meaning("操作类型")
    15     private String operateType;
    16     @Meaning("操作属性名")
    17     private String attrDisplayName;
    18     @Meaning("操作属性原值")
    19     private String oldAttrValue;
    20     @Meaning("操作属性新值")
    21     private String newAttrValue;
    22     省略get set    
    23 }
     18 
     19 /**
     20  * hibernate 事件监听器,对新增,删除,修改事件进行监听
     21  * 
     22  */
     23 @SuppressWarnings({ "serial" })
     24 public class HistoryListener implements PostInsertEventListener, PostUpdateEventListener, PreDeleteEventListener {
     25 
     26     public final static String SAVE = "1"; // 新增
     27     public final static String DELETE = "2";// 删除
     28     public final static String UPDATE = "3";// 修改
     29 
     30     /**
     31      * 监听模式
     32      * <ul>
     33      * <li>on:监听所有</li>
     34      * <li>off:不监听</li>
     35      * <li>如果是以英文逗号隔开的类名,则只监听这些类</li>
     36      * <li>这里我们把需要扩展的监听类放在配置文件中SysUtils.getSysParam只是读取配置文件的方法</li>
     37      * </ul>
     38      */
     39     private static String mode = SysUtils.getSysParam("hibernate.history.listener.classes", "off");
     40     private static String processClassStr = SysUtils.getSysParam("hibernate.history.listener.processCls");
     41     private static IHistoryListenerProcess process;
     42 
     43     /**
     44      * 捕获插入事件,并保存到历史记录信息中
     45      * 
     46      * @param event 新增事件
     47      */
     48     public void onPostInsert(PostInsertEvent event) {
     49         Object object = event.getEntity();
     50         if (isListened(object)) {
     51             logHistoryOnSaveOrDelete((EntityImpl) object, SAVE, event.getPersister());
     52         }
     53     }
     54 
     55     /**
     56      * 捕获删除事件,并保存到历史记录信息中
     57      * 
     58      * @param event 删除事件
     59      */
     60     public boolean onPreDelete(PreDeleteEvent event) {
     61         Object object = event.getEntity();
     62         if (isListened(object)) {
     63             logHistoryOnSaveOrDelete((EntityImpl) object, DELETE, event.getPersister());
     64         }
     65         return false;
     66     }
     67 
     68     /**
     69      * 捕获修改事件,并保存到历史记录信息中
     70      * 
     71      * @param enent 修改 event.getOldState() 存的是原来的数据 格式为 数据的值的顺序排列</br>
     72      *            eg: 张三,12,2016..... event.getState() 新的值 排列顺序同上
     73      * 
     74      */
     75     public void onPostUpdate(PostUpdateEvent event) {
     76         Object object = event.getEntity();
     77         if (isListened(object)) {
     78             logHistroyOnUpdate((EntityImpl) object, UPDATE, event.getOldState(), event.getState(), event.getPersister());
     79         }
     80     }
     81 
     82     /**
     83      * 新增删除的历史信息 这里写在一块主要是因为新增和删除是记录一个状态,并不会记录其他的东西
     84      * 
     85      * @param operateObject 被操作字段的对象
     86      * @param operateType 用户操作类型
     87      */
     88     private void logHistoryOnSaveOrDelete(EntityImpl operateObject, String operateType, EntityPersister persister) {
     89         History history = new History();
     90         history.setDataId(operateObject.getId());
     91         history.setOperateType(operateType);
     92         history.setOperateDate(new java.sql.Timestamp(System.currentTimeMillis()));
     93         getProcess(operateObject, history, operateType);
     94         saveHistory(history);
     95     }
     96 
     97     /**
     98      * 保存history对象
     99      * 
    100      * @param history
    101      */
    102     private void saveHistory(History history) {
    103 
    104     }
    105 
    106     /**
    107      * 获取编辑操作字段的属性名,原值,新增
    108      * 
    109      * @param newModel 监听器监听到被操作字段的对象
    110      * @param operateType 用户操作类型
    111      */
    112     private void logHistroyOnUpdate(EntityImpl newModel, String operateType, Object[] oldStates, Object[] newStates, EntityPersister persister) {
    113         String[] fields = persister.getPropertyNames();// 字段属性值
    114         if (oldStates == null || newStates == null || fields == null || oldStates.length != newStates.length || oldStates.length != fields.length) {
    115             return;
    116         }
    117         String oldValue = "";
    118         String newValue = "";
    119         for (int i = 0; i < fields.length; i++) {
    120             Object newState = newStates[i];
    121             Object oldState = oldStates[i];
    122             if (newState == oldState || (newState != null && newState.equals(oldState))) {
    123                 continue;
    124             }
    125             newValue += newState + History.SEPERATOR;// 这里用分割符拆分,方便以后处理
    126             oldValue += oldState + History.SEPERATOR;
    127         }
    128 
    129         logHistroyOnUpdate(newModel, newValue, oldValue, operateType, persister);
    130     }
    131 
    132     /**
    133      * 保存修改字段的历史信息
    134      * 
    135      * @param operateoperateObjectObject 被操作字段的对象
    136      * @param newValue 被操作字段的新值
    137      * @param oldValue 被操作字段的原值
    138      * @param fieldType 被操作字段的类型
    139      * @param fieldName 被操作字段的属性名字
    140      * @param fieldCategoryName 被操作字段对应的字段
    141      * @param operateType 用户操作类型
    142      */
    143     public void logHistroyOnUpdate(EntityImpl operateObject, String newValue, String oldValue, String operateType, EntityPersister persister) {
    144         History history = SpringContextUtil.getBean(History.class);
    145         history.setDataId(operateObject.getId());
    146         history.setOperateType(operateType);
    147         history.setOldAttrValue(oldValue);
    148         history.setNewAttrValue(newValue);
    149         history.setOperateDate(new java.sql.Timestamp(System.currentTimeMillis()));
    150         getProcess(operateObject, history, operateType);
    151         saveHistory(history);
    152     }
    153 
    154     private void getProcess(EntityImpl operateObject, History history, String type) {
    155         String[] classStr = processClassStr.split(",");
    156         for (String clazz : classStr) {
    157             if (StringUtils.isNotBlank(processClassStr)) {
    158                 Object po = null;
    159                 try {
    160                     po = Class.forName(clazz).newInstance();
    161                 } catch (Exception e) {
    162 
    163                 }
    164 
    165                 if (IHistoryListenerProcess.class.isInstance(po)) {
    166                     process = (IHistoryListenerProcess) po;
    167                 } else {
    168                     throw new SysException("要监听持久化的类必须继承IHistoryListenerProcess接口");
    169                 }
    170             }
    171             if (process == null) {
    172                 continue;
    173             }
    174             if (StringUtils.equals(type, SAVE)) {
    175                 process.postInsert(operateObject, history);
    176             } else if (StringUtils.equals(type, UPDATE)) {
    177                 process.postUpdate(operateObject, history);
    178             } else if (StringUtils.equals(type, DELETE)) {
    179                 process.preDelete(operateObject, history);
    180             }
    181             process = null;
    182         }
    183     }
    184 
    185     /**
    186      * 判断是否为监听的模块,在这里可做处理
    187      * 
    188      * @param object 监听到被操作的对象
    189      */
    190     private boolean isListened(Object object) {
    191         if (EntityImpl.class.isInstance(object) && "on".equals(mode)) {
    192             return true;
    193         }
    194         return false;
    195     }
    196 }

    这里 我们只要implements IHistoryListenerProcess 并且把类的全路径写入到配置文件中,在hibernate执行增删改的时候就会走我们的方法,这有点类似于监听者模式的意思,当然我们实现这个类也就会得到我们需要的EntityImpl类;

    这个实现只是一个便捷的想法,以后在编码中可能会用到,但是现实是我们系统中并不会只用hibernate,或者说是我们封装好的save、update等方法,如果是jdbctemplate呢,我还需要一个spring监听器,所以这就需要我们编码的规范

    和底层代码封装的丰富程度了!

  • 相关阅读:
    Vue项目和微信小程序项目的区别与比较
    在Vue中应该如何封装Axios 管理API接口
    Vue2.x 项目踩坑笔记
    微信小程序日常踩坑笔记
    面试题之JavaScript 请写一个深度克隆的函数
    面试题之JavaScript 请编写实现一个对js类型检测函数(支持检测基本类型,对象,函数,正则,时间等)
    面试题之 HTML && CSS && JavaScript 总结
    面试题之JavaScript 有一个url 'http://www.youdao.com/newcard.html?sid=50&a=5&add=9&type=all',请写一个获取url中'?'后制定参数值的函数
    面试题之JavaScript 请给Array本地对象增加一个原型方法,它用于删除数组条目中重复的条目(可能有多个),返回值是一个包含被删除的重复条目的新数组。
    面试题之JavaScript 正则相关题
  • 原文地址:https://www.cnblogs.com/sun-space/p/5770754.html
Copyright © 2011-2022 走看看