我现在有个日志要求,当更新的时候,日志里面记录哪些字段被更新!比如 user对象 有id,name,password,sex,age。
当save时,有没有办法让hibernate底层自动寻找到哪些字段被更新了。例如:更新了name一个字段。日志里面记录2011/5/26 9:20:30 user对象 name由 aaa更新为 bbb。哪位高手帮忙想下办法!!!

解决方案 »

  1.   

    Spring用Aop来实现/**
     * 
     */
    package com.sail.cot.aoplog;import java.beans.PropertyDescriptor;
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;import javax.servlet.http.HttpSession;import net.sf.ehcache.Cache;
    import net.sf.ehcache.Element;import org.apache.commons.beanutils.BeanUtils;
    import org.apache.commons.beanutils.PropertyUtils;
    import org.apache.commons.collections.map.MultiValueMap;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.directwebremoting.WebContextFactory;import com.sail.cot.dao.CotBaseDao;
    import com.sail.cot.domain.CotEmps;
    import com.sail.cot.domain.CotMail;
    import com.sail.cot.domain.CotMailRule;
    import com.sail.cot.domain.CotModLog;
    import com.sail.cot.domain.CotSyslog;
    import com.sail.cot.util.ContextUtil;
    /**
     * <p>Title: 旗航ERP管理系统(QHERP)</p>
     * <p>Description:</p>
     * <p>Copyright: Copyright (c) 2010</p>
     * <p>Company: </p>
     * <p>Create Time: Nov 23, 2010 11:55:03 AM </p>
     * <p>Class Name: AopLogAdvise.java </p>
     * @author achui
     *
     */
    public class AopLogAdvise  { /* (non-Javadoc)
     * @see org.springframework.aop.MethodBeforeAdvice#before(java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
     */
    //更新前对象的值,保存需要日志处理的对象
    private Map need2LogMap = null;
    private MultiValueMap multiValueMap = null;
    private CotBaseDao baseDao;
    Integer openLogFlag = 0;
    CotEmps emp = null;
    public AopLogAdvise(){
    }
    /**
     * 描述:初始化先决条件
     * @return
     * 返回值:boolean
     */
    private boolean InitCondition(HttpSession session){
    if(session == null){
    return false;
    }
    openLogFlag =  (Integer)session.getServletContext().getAttribute("openLogFlag");
    if(openLogFlag==null || openLogFlag == 0) return false;
    emp = (CotEmps)session.getAttribute("emp");
    Cache modLogCache = ContextUtil.getCache4ModLogCfg();
    Element element = modLogCache.get("ModuleMap");
    need2LogMap = (Map)element.getObjectValue();
    element = modLogCache.get("ModuleFieldMap");
    multiValueMap = (MultiValueMap)element.getObjectValue();
    return true;
    }
    public Object validate(ProceedingJoinPoint pjp) throws Throwable{
    if(WebContextFactory.get() == null){
    return pjp.proceed();
    }
    HttpSession session = WebContextFactory.get().getSession();
    boolean init = this.InitCondition(session);
    if(!init){
    return pjp.proceed();
    }

    Object[] args = pjp.getArgs();
    Object preObj = null;
    Object currObj = null;
    boolean isExist = false;//是否存在需要进行日志登记的对象
    String target = pjp.getTarget().getClass().getSimpleName();
    System.out.println("method==========="+pjp.getSignature().getName());
    System.out.println("=============="+target);
    //没有开启,就不进行日志记录
    if(openLogFlag == 0 || target.indexOf("$Proxy") > -1){
    return pjp.proceed();
    } Cache modLogCache = ContextUtil.getCache4ModLogCfg();
    Element element = modLogCache.get("ModuleMap");
    need2LogMap = (Map)element.getObjectValue();
    element = modLogCache.get("ModuleFieldMap");
    multiValueMap = (MultiValueMap)element.getObjectValue(); Collection<Map> coll = null;
    for(Object object : args){
    if(object ==null)continue;
    String className = object.getClass().getSimpleName();
    //数组对象,判断是否存在需要记录日志的对象
    if(object instanceof ArrayList){
    ArrayList arr = (ArrayList)object;
    for(int i = 0; i<arr.size(); i++){
    Object obj = arr.get(i);
    String objClazz = obj.getClass().getSimpleName();
    System.out.println(objClazz);
    if(need2LogMap.get(objClazz) != null){
    coll = multiValueMap.getCollection(objClazz);
    String idStr = BeanUtils.getProperty(obj, "id");
    if(idStr != null && !"".equals(idStr)){
    Integer id = new Integer(idStr);
    //获取修改前的对象
    preObj = this.getBaseDao().getById(obj.getClass(), id);
    currObj = obj;
    compareObject(preObj,currObj,emp.getId(),coll,null,null);
    }
    }else {
    if(target.equals("MailLocalServiceImpl")){
    //删除邮件模块  判断是否有勾选
    if(need2LogMap.get("CotMail") != null){
    String id =(String)obj;
    String sql =" from CotMail obj where obj.id='"+id+"'";
    List<CotMail> res = this.getBaseDao().find(sql);
    if(res.size()>0){
    CotMail cotMail =res.get(0);
    String subject =cotMail.getSubject();
    //插入记录到系统日志表
    CotSyslog syslog = new CotSyslog();
    syslog.setEmpId(emp.getId());
    syslog.setOpMessage("邮件主题: "+subject);
    syslog.setOpModule("deleteMail");
    syslog.setOpTime(new Date(System.currentTimeMillis()));
    syslog.setOpType(5); 
    List<CotSyslog> logList = new ArrayList<CotSyslog>();
    logList.add(syslog);
    this.getBaseDao().saveOrUpdateRecords(logList);

    }
    }
    }else{
    isExist = false;
    break;
    }
    }
    }
    }
    else{
    //需要进行比较
    if(need2LogMap.get(className) != null){
    coll = multiValueMap.getCollection(className);
    String idStr = BeanUtils.getProperty(object, "id");
    if(idStr != null && !idStr.equals("")){
    Integer id = new Integer(idStr);
    //获取修改前的对象
    preObj = this.getBaseDao().getById(object.getClass(), id);
    isExist = true;
    break;
    }
    }
    }
    }
    if(!isExist)
    return pjp.proceed();

    Object o = pjp.proceed();
    //TODO:在调用结束后在做方法比较
    for(Object object : args){
    String className = object.getClass().getSimpleName();
    System.out.println(className);
    //需要进行比较
    if(need2LogMap.get(className) != null){
    currObj = object;
    break;
    }
    }
    if(init){
    //做运算对比
    compareObject(preObj,currObj,emp.getId(),coll,null,null);
    }
    return o;
    }
    private boolean compareObject(Object preObj,Object currObj,Integer userId,Collection<Map> logFields,String no,Integer objectId) throws Exception{
    List list = new ArrayList();
    //String[] fields = ReflectionUtils.getDeclaredFields(preObj.getClass());
    for(Map moduleFieldMap : logFields){
    String field = (String)moduleFieldMap.get("Field");
    String fieldName = (String)moduleFieldMap.get("FieldName");
    String relateRecord = (String)moduleFieldMap.get("RelateRecord");
    Object obj = moduleFieldMap.get("ForeignKeyModule");
    Object objPro =moduleFieldMap.get("ForeignKeyModulePro");
    PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(preObj, field);
    if(pd == null) continue;
    String className = pd.getPropertyType().getSimpleName();
    //Set类型的不做处理
    if(className.equals("Set") || field.equals("id") || field.equals("picPath")) continue;
    String preVal = BeanUtils.getProperty(preObj, field);
    String curVal = BeanUtils.getProperty(currObj, field);
    String relate = BeanUtils.getProperty(currObj, relateRecord);

    if(curVal == null) continue;
    if(preVal == null && curVal.equals("")) continue;
    //有被修改过
    if(!curVal.equals(preVal)){
    CotModLog modLog = new CotModLog();
    modLog.setAddTime(new Date(System.currentTimeMillis()));
    modLog.setCurValue(curVal);
    modLog.setPreValue(preVal);
    modLog.setEmpId(userId);
    modLog.setField(field);
    modLog.setFieldName(fieldName);
    if(no != null){//说明是修改明细
    modLog.setRelateRecord(relate+"("+no+")");
    if(objectId !=null){
    modLog.setObjId(objectId);//主单ID
    }
    String objDetailId = BeanUtils.getProperty(currObj,"id");//明细ID
    modLog.setObjDetailId(Integer.parseInt(objDetailId));
    }else{
    String objId = BeanUtils.getProperty(currObj,"id");//主单ID
    modLog.setObjId(Integer.parseInt(objId));
    modLog.setRelateRecord(relate);
    }

    modLog.setModule(preObj.getClass().getSimpleName());
    if(obj != null && !obj.toString().trim().equals(""))
    modLog.setRelateModule(obj.toString());
    if(objPro != null && !objPro.toString().trim().equals("")){
    modLog.setRelateModulePro(objPro.toString());
    }

    list.add(modLog);
    }
    }
    this.getBaseDao().saveOrUpdateRecords(list);
    return true;
    }
    public void doLog(Object object,HttpSession session,String no,Integer objectId) throws Exception{
    boolean init = this.InitCondition(session);
    if(!init) return ;
    //获取需要记录日志的对象名
    Object preObj = null;
    Object currObj = null;
    boolean isExist = false;//是否存在需要进行日志登记的对象
    Collection<Map> coll = null;
    String className = object.getClass().getSimpleName();
    if(object instanceof ArrayList){
    ArrayList arr = (ArrayList)object;
    for(int i = 0; i<arr.size(); i++){
    Object obj = arr.get(i);
    String objClazz = obj.getClass().getSimpleName();
    if(need2LogMap.get(objClazz) != null){
    coll = multiValueMap.getCollection(objClazz);
    String idStr = BeanUtils.getProperty(obj, "id");
    if(idStr != null && !"".equals(idStr)){
    Integer id = new Integer(idStr);
    //获取修改前的对象
    preObj = this.getBaseDao().getById(obj.getClass(), id);
    currObj = obj;
    compareObject(preObj,currObj,emp.getId(),coll,no,objectId);
    }
    }
    }
    }else{
    //需要进行比较
    if(need2LogMap.get(className) != null){
    coll = multiValueMap.getCollection(className);
    String idStr = BeanUtils.getProperty(object, "id");
    if(idStr != null && !idStr.equals("")){
    Integer id = new Integer(idStr);
    //获取修改前的对象
    preObj = this.getBaseDao().getById(object.getClass(), id);
    currObj = object;
    compareObject(preObj,currObj,emp.getId(),coll,no,objectId);
    }
    }
    }
    }
    public CotBaseDao getBaseDao() {
    if(baseDao == null)
    baseDao = (CotBaseDao) ContextUtil.getBean("CotBaseDao");
    return baseDao;
    }
    public void setBaseDao(CotBaseDao baseDao) {
    this.baseDao = baseDao;
    }}
      

  2.   

    上面的代码,需要有一些配置表来支撑,然后通过Spring的aop特性进行配置就可以了,我目前是这么用的