在使用hibernat的時候有時須要獲取實體在更新前的某個字段的值,但hibernate沒有提供公開的api來獲取,若是使用session的get方法或用hql獲取始終只能獲取到更新後的值(我說的是在同一個會話當中,若是你另啓一個會話來獲取的話當我沒說),若是想要獲取更新前的值只能拼sql,而後用jdbc來獲取,但在研究hibernate的攔截器時候,發如今onFlushDirty中能夠獲取到更新前的值,以下:java
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) throws CallbackException;
因而仔細研究發現確實能夠經過hibernate的session來獲取更新前的值,代碼以下:sql
/** * */ package com.jason.ddoWeb.common.hibernate; import java.util.Map; import org.hibernate.Session; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.persister.entity.EntityPersister; /** * @author jasonzhang * */ public final class HibernateUtil { /** * 獲取實體的某個字段被更新前的值 * @param session hibernate的會話 * @param entityName 實體的class名全稱 * @param propertyName 須要獲取的屬性的名稱 * @return */ public final static Object getOldValue(Session session, String entityName, String propertyName) { org.hibernate.internal.SessionImpl actualSession = (org.hibernate.internal.SessionImpl)session; final PersistenceContext persistenceContext = actualSession.getPersistenceContext(); Object oldValue = null; for ( Map.Entry<Object,EntityEntry> me : persistenceContext.reentrantSafeEntityEntries() ) { EntityEntry entry = (EntityEntry) me.getValue(); if (entry.getEntityName().equals(entityName)) { Object[] loadedStates = entry.getLoadedState(); EntityPersister persister = entry.getPersister(); String[] propertyNames = persister.getPropertyNames(); for (int i=0; i<propertyNames.length; i++) { if (propertyNames[i].equals(propertyName)) { oldValue = loadedStates[i]; } } } } return oldValue; } }
調用方法以下:api
Integer oldNum = (Integer)HibernateUtil.getOldValue(super.getSession(), "com.jason.ddoWeb.entity.warning.ChannelComplaintDayEntity", "num");
其中super.getSession()是我本身代碼中獲取hibernate的session的封裝。session