Spring3和Hibernate4中使用Interceptor和Listener
项目使用了Spring3.2.6和Hibernate4.1,没有使用JPA。想在Model的基类里统一处理创建时间和最后更新时间。(https://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/listeners.html)
在实体类上使用JPA的@PrePersist等Annotation(失败)
想使用Hibernate的拦截器或监听器来处理所有model的创建时间和最后更新时间自动更新的功能。 最找使用了JPA的注解。
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@MappedSuperclass
public abstract class AbstractTimestampEntity {
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created", nullable = false)
private Date created;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "updated", nullable = false)
private Date updated;
@PrePersist
protected void onCreate() {
updated = created = new Date();
}
@PreUpdate
protected void onUpdate() {
updated = new Date();
}
}
由于项目中使用的是Hibernate而没有用JPA接口,所以@PreUpdate这些方法并没有被调用到。之前的项目使用了JPA,用这种方法是可以的。
使用Hibernate的EventListener(失败)
和上面方法类似,使用Hibernate的EventListener,发现不知如何在Spring里注册Listener,参考了http://stackoverflow.com/questions/8616146/eventlisteners-using-hibernate-4-0-with-spring-3-1-0-release里的方法注册成功了:
@Component
@Lazy(false)
public class HibernateEventWiring {
@Autowired
private SessionFactory sessionFactory;
@Autowired
private SomeHibernateListener listener;
@PostConstruct
public void registerListeners() {
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.POST_COMMIT_INSERT).appendListener(listener);
registry.getEventListenerGroup(EventType.POST_COMMIT_UPDATE).appendListener(listener);
}
}
因为Spring的配置文件里可能会把Bean的初始化默认配置成lazy,default-lazy-init="true"
,所以在上面这个Bean里加上了@Lazy(false)的注解。
配置是成功了,但是,Listener还是没有被调用到。
使用Hibernate的Intecepter(成功)
实现一个Interceper:
public class BaseModelInterceptor extends EmptyInterceptor {
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
if (entity instanceof BaseModel) {
for ( int i=0; i<propertyNames.length; i++ ) {
if ( "createdDate".equals( propertyNames[i] ) ) {
state[i] = new Date();
return true;
}
}
}
return true;
}
}
然后在配置文件里配置:
<bean id="baseModelInterceptor" class="xxx.BaseModelInterceptor"></bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="entityInterceptor" ref="baseModelInterceptor"/>
</bean>
这样就可以了。
但是注意,BaseModelInterceptor里想下面的代码是不可以的,为什么呢?
if (entity instanceof BaseModel) {
BaseModel model = (BaseModel) entity;
model.setLastUpdated(new Date());
model.setCreatedDate(new Date());
}
System.out.println(entity);
return true;
相关文章
- 基于-SLF4J-MDC-机制的日志链路追踪配置属性
ums: # ================ 基于 SLF4J MDC 机制的日志链路追踪配置属性 ================ mdc: # 是否支持基于 SLF4J MDC
- ajax-跨域访问
ajax 跨域访问 <!DOCTYPE html> <html xmlns:th="http://www.w3.org/1999/xhtml"> <head>
- 给第三方登录时用的数据库表-user_connection-与-auth_token-添加-redis-cache
spring: # 设置缓存为 Redis cache: type: redis # redis redis: host: 192.168.88.88 port
- Java动态代理
Jdk动态代理 通过InvocationHandler和Proxy针对实现了接口的类进行动态代理,即必须有相应的接口 应用 public class TestProxy { public
- Java读取classpath中的文件
public void init() { try { //URL url = Thread.currentThread().getContextClassLo
随机推荐
- 基于-SLF4J-MDC-机制的日志链路追踪配置属性
ums: # ================ 基于 SLF4J MDC 机制的日志链路追踪配置属性 ================ mdc: # 是否支持基于 SLF4J MDC
- ajax-跨域访问
ajax 跨域访问 <!DOCTYPE html> <html xmlns:th="http://www.w3.org/1999/xhtml"> <head>
- 给第三方登录时用的数据库表-user_connection-与-auth_token-添加-redis-cache
spring: # 设置缓存为 Redis cache: type: redis # redis redis: host: 192.168.88.88 port
- Java动态代理
Jdk动态代理 通过InvocationHandler和Proxy针对实现了接口的类进行动态代理,即必须有相应的接口 应用 public class TestProxy { public
- Java读取classpath中的文件
public void init() { try { //URL url = Thread.currentThread().getContextClassLo