这里是我看到的一个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 *
33 * - on:监听所有
34 * - off:不监听
35 * - 如果是以英文逗号隔开的类名,则只监听这些类
36 * - 这里我们把需要扩展的监听类放在配置文件中SysUtils.getSysParam只是读取配置文件的方法
37 *
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() 存的是原来的数据 格式为 数据的值的顺序排列
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 history101 */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监听器,所以这就需要我们编码的规范
和底层代码封装的丰富程度了!