Spring3和Hibernate4中使用Interceptor和Listener

技术文档网 2021-04-27

项目使用了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();
    }
}

http://stackoverflow.com/questions/221611/creation-timestamp-and-last-update-timestamp-with-hibernate-and-mysql

由于项目中使用的是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;

相关文章

  1. 基于-SLF4J-MDC-机制的日志链路追踪配置属性

    ums: # ================ 基于 SLF4J MDC 机制的日志链路追踪配置属性 ================ mdc: # 是否支持基于 SLF4J MDC

  2. ajax-跨域访问

    ajax 跨域访问 &lt;!DOCTYPE html&gt; &lt;html xmlns:th="http://www.w3.org/1999/xhtml"&gt; &lt;head&gt;

  3. 给第三方登录时用的数据库表-user_connection-与-auth_token-添加-redis-cache

    spring: # 设置缓存为 Redis cache: type: redis # redis redis: host: 192.168.88.88 port

  4. Java动态代理

    Jdk动态代理 通过InvocationHandler和Proxy针对实现了接口的类进行动态代理,即必须有相应的接口 应用 public class TestProxy { public

  5. Java读取classpath中的文件

    public void init() { try { //URL url = Thread.currentThread().getContextClassLo

随机推荐

  1. 基于-SLF4J-MDC-机制的日志链路追踪配置属性

    ums: # ================ 基于 SLF4J MDC 机制的日志链路追踪配置属性 ================ mdc: # 是否支持基于 SLF4J MDC

  2. ajax-跨域访问

    ajax 跨域访问 &lt;!DOCTYPE html&gt; &lt;html xmlns:th="http://www.w3.org/1999/xhtml"&gt; &lt;head&gt;

  3. 给第三方登录时用的数据库表-user_connection-与-auth_token-添加-redis-cache

    spring: # 设置缓存为 Redis cache: type: redis # redis redis: host: 192.168.88.88 port

  4. Java动态代理

    Jdk动态代理 通过InvocationHandler和Proxy针对实现了接口的类进行动态代理,即必须有相应的接口 应用 public class TestProxy { public

  5. Java读取classpath中的文件

    public void init() { try { //URL url = Thread.currentThread().getContextClassLo