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

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

posted @ 2016-08-14 18:43  user_孙  阅读(454)  评论(0编辑  收藏  举报