该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-11-03
对于Audit这个功能而言, 偶只用实现onFlushDirty和onSave, 其他的倒用不到:
public abstract class AbstractAuditInterceptor implements Interceptor, Serializable { public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types); throws CallbackException { if (entity instanceof Auditable); { AuditInfo ai = ((Auditable); entity);.getAuditInfo();; if (ai == null); { ai = new AuditInfo();; ((Auditable); entity);.setAuditInfo(ai);; } ai.setLastUpdated(new Date(););; ai.setUpdatedBy(getUserId(););; } return false; } public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types); throws CallbackException { if (entity instanceof Auditable); { AuditInfo ai = ((Auditable); entity);.getAuditInfo();; if (ai == null); { ai = new AuditInfo();; ((Auditable); entity);.setAuditInfo(ai);; } ai.setCreated(new Date(););; ai.setCreatedBy(getUserId(););; } return false; } public abstract String getUserId();; } 用AOP做这种事情? 哼哼, 偶不爽...... |
|
返回顶楼 | |
发表时间:2005-01-27
public boolean onFlushDirty(Object entity, Serializable id, Object[] newValues, Object[] oldValues, String[] properties, Type[] types); throws CallbackException { System.out.println(Arrays.asList(properties););; System.out.println(Arrays.asList(oldValues););; // is null System.out.println(Arrays.asList(newValues););; System.out.println(oldValues);; System.out.println(newValues);; return false; } 为何oldValues返回null,properties和newValues都正常! |
|
返回顶楼 | |
发表时间:2005-01-27
water 写道 为何oldValues返回null,properties和newValues都正常!
版本?代码?配置?偶都看不到...... |
|
返回顶楼 | |
发表时间:2005-01-27
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="dataSource"> <ref local="dataSource"/> </property> <property name="mappingDirectoryLocations"> <list> <value>com/test/pojo</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">net.sf.hibernate.dialect.Oracle9Dialect</prop> </props> </property> <property name="entityInterceptor"> <ref local="historyInterceptor"/> </property> </bean> <bean id="historyInterceptor" class="com.test.interceptor.HistoryInterceptor"> </bean> public class HistoryInterceptor implements Interceptor { // other method public boolean onFlushDirty(Object entity, Serializable id, Object[] newValues, Object[] oldValues, String[] properties, Type[] types); throws CallbackException { System.out.println(Arrays.asList(properties););; // ok System.out.println(entity.getClass();.getName(););; // ok System.out.println(oldValues);; // null System.out.println(newValues);; // ok return false; } } test code; public void testUpdateGoods(); throws Exception { Goods goods = this.goodsDAO.getGoods(new Integer(12225););; String oldName = goods.getName();; goods.setName(oldName + "1");; this.goodsDAO.updateGoods(goods);; goods = this.goodsDAO.getGoods(new Integer(12225););; assertEquals(oldName + "1", goods.getName(););; } |
|
返回顶楼 | |
发表时间:2005-01-27
Session session = sessionFactory.openSession(new HistoryInterceptor(););; Transaction tx = session.beginTransaction();; Goods goods = (Goods); session.load(Goods.class, new Integer(12225););; String oldName = goods.getName();; goods.setName(oldName + "1");; session.update(goods);; session.flush();; tx.commit();; goods = (Goods); session.load(Goods.class, new Integer(12225););; session.close();; sessionFactory.close();; assertEquals(oldName + "1", goods.getName(););; 这样就OK了! Spring的LocalSessionFactoryBean是这样实现的 if (this.entityInterceptor != null); { // set given entity interceptor at SessionFactory level config.setInterceptor(this.entityInterceptor);; } 请问 Session session = sessionFactory.openSession(new HistoryInterceptor(););; 与 configuration.setInterceptor(this.entityInterceptor);; 有什么不同? |
|
返回顶楼 | |
发表时间:2007-01-31
引用 写自己的Interceptor目前有一个问题就是它需要实现的方法太多, 有一些还能通过名字直接看出来意义, 比如onSave, onLoad, 有一些就得看javadoc, 甚至查看hibernate的源代码了. 所以Hibernate 3把Interceptor咔嚓掉, 用更丰富的Event/EventListener来达到同样的可扩展性目的. hibernate3里不是可以继承EmptyInterceptor这个类吗?可以根据需要来重写啊。
|
|
返回顶楼 | |
发表时间:2007-01-31
详细的请看这里http://blog.sina.com.cn/u/49bc2ffd010007gd
hibernate.cfg.xml的内容如下: <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property> <property name="hibernate.connection.username">work</property> <property name="hibernate.connection.password">caecaodb</property> <property name="hibernate.show_sql">true</property> <property name="dialect">net.sf.hibernate.dialect.OracleDialect</property> <property name="hibernate.connection.isloation">2</property> <mapping resource="hibernate/audit/Customer.hbm.xml"/> <mapping resource="hibernate/audit/AuditLogRecord.hbm.xml"/> </session-factory> </hibernate-configuration> 4.在包hibernate.audit下新建如下内容(附相关说明) 接口: Auditable.java //是为了在保存日志记录到表AUDIT_LOGS时得到持久类的id. package hibernate.audit; public interface Auditable { public Long getId(); } 类AuditLogRecord.java //该类是日志表的持久久 package hibernate.audit; import java.util.Date; public class AuditLogRecord { public Long entityid; public String message; public Class entityClass; public Date created; public AuditLogRecord(String message, Long entityid, Class entityClass) { this.message = message; this.entityid = entityid; this.entityClass = entityClass; this.created = new Date(); } public AuditLogRecord() { } } 类:Customer.java //该类是实体类,实现了接口Auditable.java,Auditable.java主要是为了让Customer类必须有getId()方法,以便在保存日志时能得到实体类的id值 package hibernate.audit; public class Customer implements Auditable{ Long id; String name; public Customer() {} public Customer(String name) { this.name=name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 类:HibernateUtil.java //用于管理session package hibernate.audit; import net.sf.hibernate.*; import net.sf.hibernate.cfg.Configuration; public class HibernateUtil { private static SessionFactory sessionFactory; public static final ThreadLocal session= new ThreadLocal(); static { try { // 实例化一个SessionFactory对象 //System.out.println("通过静态模块创建一个SessionFactory"); sessionFactory = new Configuration().configure() .buildSessionFactory(); } catch (HibernateException ex) { throw new RuntimeException("Configuration problem:" + ex.getMessage(), ex); } } public static Session getSession(Interceptor interceptor) //将session和拦截器相绑定 throws HibernateException { Session tempsession = (Session) session.get(); if (tempsession == null || !tempsession.isOpen()) { tempsession = sessionFactory.openSession(interceptor); session.set(tempsession); } return tempsession; } public static void closeSession() throws HibernateException { Session s = (Session) session.get(); if (s != null) { s.close(); } } } 类:AutitLog.java //该类完成日志记录的保存 注:因为传入的session的状态不稳定,因此通过它来得到jdbc连接,再通过该jdbc连接来得到一个新的session package hibernate.audit; import java.sql.Connection; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; public class AutitLog { public static void logEvent(String message, Auditable entity,Session session) { Session tempSession = null; try { SessionFactory sessionFactory = session.getSessionFactory(); Connection conn = session.connection(); tempSession = sessionFactory.openSession(conn); AuditLogRecord record=new AuditLogRecord(message,entity.getId(),entity.getClass()); tempSession.save(record); tempSession.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { tempSession.close(); } catch (Exception e) { e.printStackTrace(); } } } } 类:AuditLogIntercepor.java //该类实现了拦截器接口,本例只实现了insert,update,delete日志,因此只在这三种数据操作的相关方法中加入了业务逻辑 package hibernate.audit; import java.io.Serializable; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import net.sf.hibernate.CallbackException; import net.sf.hibernate.Interceptor; import net.sf.hibernate.Session; import net.sf.hibernate.type.Type; public class AuditLogIntercepor implements Interceptor,Serializable { private static final long serialVersionUID = 1L; private Session session; private Set inserts = new HashSet(); private Set updates = new HashSet(); private Set delete = new HashSet(); public void setSession(Session session) { this.session = session; } public boolean onLoad(Object arg0, Serializable arg1, Object[] arg2, String[] arg3, Type[] arg4) throws CallbackException { // TODO 自动生成方法存根 return false; } //当flush()方法检查到脏对象时调用该方法 public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] type) throws CallbackException { // TODO 自动生成方法存 System.out.println("onFlushDirty()执行,传入的类为:"+entity.getClass()); if (entity instanceof Auditable) { updates.add(entity); } return false; } //保存一个对象之前Hibernate自动调用该方法 public boolean onSave(Object entity, Serializable arg1, Object[] arg2, String[] arg3, Type[] arg4) throws CallbackException { // TODO 自动生成方法存根 System.out.println("onSave()执行,传入的类为:"+entity.getClass()); if (entity instanceof Auditable) { inserts.add(entity); } return false; } //删除一个对象之前Hibernate自动调用该方法 public void onDelete(Object entity, Serializable arg1, Object[] arg2, String[] arg3, Type[] arg4) throws CallbackException { // TODO 自动生成方法存根 System.out.println("onDelete()执行,传入的类为:"+entity.getClass()); if (entity instanceof Auditable) { delete.add(entity); } } public void preFlush(Iterator arg0) throws CallbackException { // TODO 自动生成方法存根 } public void postFlush(Iterator entities) throws CallbackException { // TODO 自动生成方法存根 try { Iterator it = updates.iterator(); while (it.hasNext()) { Auditable entity = (Auditable) it.next(); AutitLog.logEvent("update", entity, session); } it = inserts.iterator(); while (it.hasNext()) { Auditable entity = (Auditable) it.next(); AutitLog.logEvent("insert", entity, session); } it = delete.iterator(); while (it.hasNext()) { Auditable entity = (Auditable) it.next(); AutitLog.logEvent("delete", entity, session); } } catch (Exception e) { } finally { inserts.clear(); updates.clear(); delete.clear(); } } public Boolean isUnsaved(Object arg0) { // TODO 自动生成方法存根 return null; } public int[] findDirty(Object arg0, Serializable arg1, Object[] arg2, Object[] arg3, String[] arg4, Type[] arg5) { // TODO 自动生成方法存根 return null; } public Object instantiate(Class arg0, Serializable arg1) throws CallbackException { // TODO 自动生成方法存根 return null; } } 映射文件:AuditLogRecord.hbm.xml //用于完成日志表的日志持久类的映射 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" > <hibernate-mapping> <class name="hibernate.audit.AuditLogRecord" table="audit_logs"> <id type="long" column="ID"> <generator class="increment"/> </id> <property name="entityid" type="long" column="ENTITY_ID" access="field" not-null="true" /> <property name="message" type="string" column="MESSAGE" access="field" not-null="true"/> <property name="entityClass" type="class" column="ENTITY_CLASS" access="field" not-null="true" /> <property name="created" type="timestamp" column="CREATED" access="field" not-null="true"/> </class> </hibernate-mapping> 映射文件:Customer.hbm.xml //用于完成customer类和customer表的映射 <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" > <hibernate-mapping> <class name="hibernate.audit.Customer" table="customer"> <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" type="string" column="NAME" /> </class> </hibernate-mapping> 类:HibernateTest.java //含main()方法的入口类 package hibernate.audit; import net.sf.hibernate.LockMode; import net.sf.hibernate.Session; import net.sf.hibernate.Transaction; public class HibernateTest { public static void main(String[] args) throws HibernateException, SQLException, IOException { new HibernateTest().doit(); } public void doit() throws HibernateException, SQLException, IOException { AuditLogIntercepor interceptor = new AuditLogIntercepor(); Session session = HibernateUtil.getSession(interceptor); //拦截器类AuditLogIntercepor要与session关联才能激发拦截器 interceptor.setSession(session); Transaction tx = session.beginTransaction(); Customer customer = new Customer("test_log"); session.save(customer);//保存时生成日志 customer.setName("my_log"); //更新时生成日志 Customer cs = (Customer) session.load(Customer.class, new Long(1),LockMode.UPGRADE);//悲观锁定;id=1的记录,在新建customer表的时候已经建立 session.delete(cs);//删除时生成日志 tx.commit(); session.close(); } } 最后,将HibernateTest.java以java应用程序方式运行,再看表customer已有一条id=1,name="test_log"的记录;audit_logs表中则有三条日志记录,记录了insert,update,delete AuditLogIntercepor这个类在Hibernate3里可以继承EmptyInterceptor |
|
返回顶楼 | |