EventListner机制在Hibernate3 和 Hibernate4中的区别

一次偶然的机会发现了他们的差别

最近正在学习hibernate,学习资料里用的是hibernate3作为背景,而我从SourceForge上下载了最新hibernate-release-4.3.8.Final.zip。前面的练习一切正常:包括基本的全局配置,实体配置,实体间关联关系的定义以及锁机制等等。最后在处理监听器(EventListener)的时候发现不论在hibernate.cfg.xml里怎么定义拦截器都不起作用。后来新下载了一个hibernate-3.2.5.ga.zip,重新运行,一切如常。在网上也查了很多资料来解决hibernate4里监听器的问题,发现写得都比较含糊,有些地方是和Spring以及Structs一起的解决办法,都没有实际解决我的问题。后来在stackoverflow上看到一个介绍(网址在最后),研读之后,对我自己的代码基于hibernate4做了相应的修改,可以正常工作了。

前面说了这么多废话,现在进入正题吧。

之前已经定义好了一个Student的class。要做的事情很简单,就是在新增一条记录的时候让自己定义的EventListner在Sname后加上随机数。

hibernate.cfg.xml中的mapping关系定义如下:

<mapping resource="domain/Student.hbm.xml" />

Student.java定义如下:(get/set方法已省略)

public class Student {
	
	private int Sid;
	private String  Sname, Sage, Ssex;
	private int version;
}
自定义的EventListner类SaveStudentListner.java如下:

public class SaveStudentListener implements SaveOrUpdateEventListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public void onSaveOrUpdate(SaveOrUpdateEvent arg0)
			throws HibernateException {
		// TODO Auto-generated method stub
		System.out.println("Catch save event.");
		if (arg0.getObject() instanceof domain.Student){
			Student st = (Student)arg0.getObject();
			System.out.println("Handle save student: " + st.getSname());			
			int i = (int) (100*Math.random());
			System.out.println("Random number is: " + i);
			st.setSname(st.getSname() + i);
		}

	}

}

额外定义了一个处理hibernate 的session的util类:

public class HibernateUtil {
	private static SessionFactory sf;

	private HibernateUtil() {
	}
	static {
		Configuration cf = new Configuration();
		cf.configure();
		sf = cf.buildSessionFactory();
	}
	public static SessionFactory getSessionFactory() {
		return sf;
	}
	public static Session getSession() {
		return sf.openSession();
	}

}

hibernate3中如何实现事件监听

在hibernate.cfg.xml中新加一个section:

		<!-- Only available for Hibernate 3.0 -->
		<event type="save">
			<listener class="domain.SaveStudentListener" />	
			<listener class="org.hibernate.event.def.DefaultSaveOrUpdateEventListener"/>		
		</event>


测试类定义如下:

	public static void main(String[] args) {
		add();
	}
	static void add() {
		Session s = null;
		Transaction tx = null;
		try {			
			s = HibernateUtil.getSession();
			tx = s.beginTransaction();
			Student st = new Student();
			st.setSname("Event3.0");			
			s.save(st);		
			tx.commit();
		}catch(Exception e){
			System.out.println("Error occur during add Student: " + e.getMessage());
		}
		finally {
			if (s != null)
				s.close();
		}
	}

运行test类,得到如下结果:

Hibernate: insert into Student (version, Sname, Sage, Ssex) values (?, ?, ?, ?)
Catch save event.
Handle save student: Event4.0
Random number is: 1
Hibernate: update Student set version=?, Sname=?, Sage=?, Ssex=? where Sid=? and version=?

如果只定义了<listener class="domain.SaveStudentListener" />,会导致最后没有数据库插入的sql,必须加上<listener class="org.hibernate.event.def.DefaultSaveOrUpdateEventListener"/>

hibernate4中如何实现事件监听

现在把所有hibernate3相关的jar包替换为hibernate4的jar包 (hibernate-release-4.3.8.Final\lib\required下所有的jar包),重新运行一次test类。

得到结果如下:

Hibernate: insert into Student (version, Sname, Sage, Ssex) values (?, ?, ?, ?)

为什么没有进入到eventlistener呢?

因为hibernate4中的eventlistener机制发生了翻天覆地的变化,hibernate4不再从hibernate.cfg.xml中读取event listener相关信息。

那怎么办?

hibernate4提供了全新的办法,我们把test类稍做修改(高亮部分):

注意高亮部分:要传递自定义的event listener的class名:SaveStudentListener.class

	public static void main(String[] args) {

		//For Hibernate 4.0
		//http://in.relation.to/Bloggers/EventListenerRegistration
		//org.hibernate.integrator.spi.Integrator		
<span style="white-space:pre">		</span>final EventListenerRegistry eventListenerRegistry = ((SessionFactoryImpl) HibernateUtil.getSessionFactory()).getServiceRegistry().getService( EventListenerRegistry.class );
		eventListenerRegistry.appendListeners( EventType.SAVE, SaveStudentListener.class );
		add();
		
		//update(2);
	}
	static void add() {
		Session s = null;
		Transaction tx = null;
		try {			
			s = HibernateUtil.getSession();
			//s = new Configuration().configure().buildSessionFactory().openSession();
			tx = s.beginTransaction();
			Student st = new Student();
			st.setSname("Event4.0");			
			s.save(st);
		// 交换以上两句的位置,看Hibernate执行的sql语句。会再增加一条更新操作。
			tx.commit();
		}catch(Exception e){
			System.out.println("Error occur during add Student: " + e.getMessage());
		}
		finally {
			if (s != null)
				s.close();
		}
	}
运行结果如下:

Hibernate: insert into Student (version, Sname, Sage, Ssex) values (?, ?, ?, ?)
Catch save event.
Handle save student: Event4.0
Random number is: 70
Hibernate: update Student set version=?, Sname=?, Sage=?, Ssex=? where Sid=? and version=?

个人觉得新的方法其实要简单一些,不用担心覆盖掉原有的eventlistener。

hibernate4提供了三种添加event listener的方法,正如http://in.relation.to/Bloggers/EventListenerRegistration中所说:

        // EventListenerRegistry defines 3 ways to register listeners:
        //     1) This form overrides any existing registrations with 
        eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, myCompleteSetOfListeners );
        //     2) This form adds the specified listener(s) to the beginning of the listener chain
        eventListenerRegistry.prependListeners( EventType.AUTO_FLUSH, myListenersToBeCalledFirst );
        //     3) This form adds the specified listener(s) to the end of the listener chain
        eventListenerRegistry.appendListeners( EventType.AUTO_FLUSH, myListenersToBeCalledLast );








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌拉乌拉有人爱

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值