9.9. 拦截器(Interceptors)
Interceptor接口提供从session到你的应用程序的回调方法,让你的程序可以观察和在持久化对象保存/更改/删除或者装载的时候操作它的属性。一种可能的用途是用来监视统计信息。比如,下面的Interceptor会自动在一个Auditable创建的时候设置其createTimestamp,并且当它被更改的时候,设置其lastUpdateTimestamp属性。
package net.sf.hibernate.test;
import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;
import net.sf.hibernate.Interceptor;
import net.sf.hibernate.type.Type;
public class AuditInterceptor implements Interceptor, Serializable {
private int updates;
private int creates;
public void onDelete(Object entity,
Serializable id,
Object[] state,
String[] propertyNames,
Type[] types) {
// do nothing
}
public boolean onFlushDirty(Object entity,
Serializable id,
Object[] currentState,
Object[] previousState,
String[] propertyNames,
Type[] types) {
if ( entity instanceof Auditable ) {
updates++;
for ( int i=0; i < propertyNames.length; i++ ) {
if ( "lastUpdateTimestamp".equals( propertyNames[i] ) ) {
currentState[i] = new Date();
return true;
}
}
}
return false;
}
public boolean onLoad(Object entity,
Serializable id,
Object[] state,
String[] propertyNames,
Type[] types) {
return false;
}
public boolean onSave(Object entity,
Serializable id,
Object[] state,
String[] propertyNames,
Type[] types) {
if ( entity instanceof Auditable ) {
creates++;
for ( int i=0; i<propertyNames.length; i++ ) {
if ( "createTimestamp".equals( propertyNames[i] ) ) {
state[i] = new Date();
return true;
}
}
}
return false;
}
public void postFlush(Iterator entities) {
System.out.println("Creations: " + creates + ", Updates: " + updates);
}
public void preFlush(Iterator entities) {
updates=0;
creates=0;
}
......
......
}
当session被创建的时候,就应该指定拦截器。
Session session = sf.openSession( new AuditInterceptor() );
9.10. 元数据(Metadata) API
Hibernate对所有的实体和值类型都需要一个非常丰富的元级别(meta-level)模型。有时候,这个模型对应用程序本身也会非常有用。比如说,应用程序可能使用Hibernate的元数据来实现一种“智能”的深度拷贝算法,来理解哪些对象应该被拷贝(比如,可变的值类型),那些不应该(不可变的值类型和可能的被关联的实体)。
Hibernate通过ClassMetadata接口,CollectionMetadata接口和Type对象树,暴露出元数据。可以通过SessionFactory获取metadata接口的实例。
Cat fritz = ......;
Long id = (Long) catMeta.getIdentifier(fritz);
ClassMetadata catMeta = sessionfactory.getClassMetadata(Cat.class);
Object[] propertyValues = catMeta.getPropertyValues(fritz);
String[] propertyNames = catMeta.getPropertyNames();
Type[] propertyTypes = catMeta.getPropertyTypes();
// get a Map of all properties which are not collections or associations
// TODO: what about components?
Map namedValues = new HashMap();
for ( int i=0; i<propertyNames.length; i++ ) {
if ( !propertyTypes[i].isEntityType() && !propertyTypes[i].isCollectionType() ) {
namedValues.put( propertyNames[i], propertyValues[i] );
}
}