因为之前项目中用到的框架版本是spring3+hibernate3 在配置hibernate的监听事件的时候,一般是在applicationContext.xml中这样配置:
<!-- Hibernate配置 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="namingStrategy">
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache/ehcache-hibernate-local.xml</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
</props>
</property>
<property name="packagesToScan" value="com.pengtu.entity" />
<property name="eventListeners">
<map>
<entry key="save-update">
<list>
<bean class="com.pengtu.dao.hibernate.AuditListener" />
<bean class="org.hibernate.event.def.DefaultSaveOrUpdateEventListener" />
</list>
</entry>
</map>
</property>
</bean>
我们查看
org.springframework.orm.hibernate3.annotation.
AnnotationSessionFactoryBean 的父类LocalSessionFactoryBean中 就有eventListeners属性的声明;
其中key-type的值有多种 具体如下:
因为系统要对新增和更新的数据做一部分共同的操作,比如:给每个新增的实体类添加创建时间、添加数据的时候将新增的信息输出到日志文件中等等。所以key-type选择了 save-update ,根据自己的需求来定义。
但是目前系统的hibernate换成了4.*版本,通过查看jar包下面的文件,发现4.*以后的版本都没有了对eventListeners的支持,如果还是按照上面的形式配置,会提示错误,
先贴上我当时配置时的代码 (还没有添加eventListeners):
<!-- 配置hibernate session工厂 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache/ehcache-hibernate-local.xml</prop>
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
</props>
</property>
<!-- 自动扫描注解方式配置的hibernate类文件 -->
<property name="packagesToScan">
<list>
<value>com.pengtu.gsj.entity</value>
</list>
</property>
</bean>
通过查看
org.springframework.orm.hibernate4.
LocalSessionFactoryBean 的
源码,发现已经不支持EventListener了,但是肯定有新的方式来支持,通过查阅资料,发现4.*版本后都是通过注解的方式来配置,贴出具体的操作流程:
1.新增事件监听器: HibernateEventWiring:
package com.pengtu.gsj.dao.hibernate;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.hibernate.SessionFactory;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.util.Assert;
/**
* @author zl
* @version 创建时间:2017年3月30日 上午11:02:33 类说明
*/
public class HibernateEventWiring {
private SessionFactory sessionFactory;
private Map<String, Object> listeners;
@PostConstruct
public void registerListeners() {
Assert.notNull(sessionFactory);
EventListenerRegistry eventListenerRegistry = ((SessionFactoryImpl) sessionFactory)
.getServiceRegistry().getService(EventListenerRegistry.class);
for (String key : listeners.keySet()) {
EventType eventType = EventType.resolveEventTypeByName(key);
eventListenerRegistry.getEventListenerGroup(eventType).appendListener(listeners.get(key));
}
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void setListeners(Map<String, Object> listeners) {
this.listeners = listeners;
}
}
可能有些人对@Postconstruct 这里简单提一下:
从Java EE5规范开始,Servlet增加了两个影响Servlet生命周期的注解(Annotation):@PostConstruct和@PreConstruct。这两个注解被用来修饰一个非静态的void()方法.而且这个方法不能有抛出异常声明。
使用方式,例如:
@PostConstruct //方式1
public void someMethod(){
...
}
public @PostConstruct void someMethod(){ //方式2
...
}
@PostConstruct说明
被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
@PreConstruct说明
被@PreConstruct修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreConstruct修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。
2.新增事件处理事件类:AccountSaveUpdateEventListener 方法中最好将key-type包含进去。
package com.pengtu.gsj.dao.hibernate;
import org.hibernate.HibernateException;
import org.hibernate.event.spi.SaveOrUpdateEvent;
import org.hibernate.event.spi.SaveOrUpdateEventListener;
/**
* @author zl
* @version 创建时间:2017年3月30日 上午11:16:47
* 类说明
*/
public class AccountSaveUpdateEventListener implements SaveOrUpdateEventListener {
/**
*
*/
private static final long serialVersionUID = -5890362089838366308L;
@Override
public void onSaveOrUpdate(SaveOrUpdateEvent event)
throws HibernateException {
System.out.println("测试在保存和更新操作之前的处理方法");
}
}
注:
此处继承的接口根据自己的key-type来
3.在配置文件中配置监听:
<bean class="com.pengtu.gsj.dao.hibernate.HibernateEventWiring">
<property name="sessionFactory" ref="sessionFactory"></property>
<property name="listeners">
<map>
<entry key="save-update" value-ref="accountUpdateEventListener"></entry>
</map>
</property>
</bean>
<bean id="accountUpdateEventListener" class="com.pengtu.gsj.dao.hibernate.AccountSaveUpdateEventListener" ></bean>
4.新增测试方法:
public class UserTest extends AbstractContextControllerTests{
@Autowired
private UserService userService;
@Test
public void setUser() throws Exception{
User user = new User();
user.setUsername("TM");
user.setPassword("1234");
user.setCreateDate(new Date());
user.setDelFlag("0");
userService.setUser(user);
}
}
5.测试结果:
测试成功!
成功解决。。。
感谢大家的支持!