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监听器,所以这就需要我们编码的规范

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

  • 相关阅读:
    【leetcode】1215.Stepping Numbers
    【leetcode】1214.Two Sum BSTs
    【leetcode】1213.Intersection of Three Sorted Arrays
    【leetcode】1210. Minimum Moves to Reach Target with Rotations
    【leetcode】1209. Remove All Adjacent Duplicates in String II
    【leetcode】1208. Get Equal Substrings Within Budget
    【leetcode】1207. Unique Number of Occurrences
    【leetcode】689. Maximum Sum of 3 Non-Overlapping Subarrays
    【leetcode】LCP 3. Programmable Robot
    【leetcode】LCP 1. Guess Numbers
  • 原文地址:https://www.cnblogs.com/sun-space/p/5770754.html
Copyright © 2011-2022 走看看