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监听器,所以这就需要我们编码的规范
和底层代码封装的丰富程度了!