📄 events.html
字号:
return false; } public void afterTransactionCompletion(Transaction tx) { if ( tx.wasCommitted() ) { System.out.println("Creations: " + creates + ", Updates: " + updates, "Loads: " + loads); } updates=0; creates=0; loads=0; }}</pre><p> 拦截器可以有两种:<tt class="literal">Session</tt>范围内的,和<tt class="literal">SessionFactory</tt>范围内的。 </p><p> 当使用某个重载的SessionFactory.openSession()使用<tt class="literal">Interceptor</tt>作为参数调用打开一个session的时候,就指定了<tt class="literal">Session</tt>范围内的拦截器。 </p><pre class="programlisting">Session session = sf.openSession( new AuditInterceptor() );</pre><p> <tt class="literal">SessionFactory</tt>范围内的拦截器要通过<tt class="literal">Configuration</tt>中注册,而这必须在创建<tt class="literal">SessionFactory</tt>之前。在这种情况下,给出的拦截器会被这个<tt class="literal">SessionFactory</tt>所打开的所有session使用了;除非session打开时明确指明了使用的拦截器。<tt class="literal">SessionFactory</tt>范围内的拦截器,必须是线程安全的,因为多个session可能并发使用这个拦截器,要因此小心不要保存与session相关的状态。 </p><pre class="programlisting">new Configuration().setInterceptor( new AuditInterceptor() );</pre></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="objectstate-events"></a>12.2. 事件系统(Event system) </h2></div></div><div></div></div><p> 如果需要响应持久层的某些特殊事件,你也可以使用Hibernate3的事件框架。 该事件系统可以用来替代拦截器,也可以作为拦截器的补充来使用。 </p><p> 基本上,<tt class="literal">Session</tt>接口的每个方法都有相对应的事件。比如 <tt class="literal">LoadEvent</tt>,<tt class="literal">FlushEvent</tt>,等等(查阅XML配置文件 的DTD,以及<tt class="literal">org.hibernate.event</tt>包来获得所有已定义的事件的列表)。当某个方 法被调用时,Hibernate <tt class="literal">Session</tt>会生成一个相对应的事件并激活所 有配置好的事件监听器。系统预设的监听器实现的处理过程就是被监听的方法要做的(被监听的方法所做的其实仅仅是激活监听器, “实际”的工作是由监听器完成的)。不过,你可以自由地选择实现 一个自己定制的监听器(比如,实现并注册用来处理处理<tt class="literal">LoadEvent</tt>的<tt class="literal">LoadEventListener</tt>接口), 来负责处理所有的调用<tt class="literal">Session</tt>的<tt class="literal">load()</tt>方法的请求。 </p><p> 监听器应该被看作是单例(singleton)对象,也就是说,所有同类型的事件的处理共享同一个监听器实例,因此监听器 不应该保存任何状态(也就是不应该使用成员变量)。 </p><p> 用户定制的监听器应该实现与所要处理的事件相对应的接口,或者从一个合适的基类继承(甚至是从Hibernate自带的默认事件监听器类继承, 为了方便你这样做,这些类都被声明成non-final的了)。用户定制的监听器可以通过编程使用<tt class="literal">Configuration</tt>对象 来注册,也可以在Hibernate的XML格式的配置文件中进行声明(不支持在Properties格式的配置文件声明监听器)。 下面是一个用户定制的加载事件(load event)的监听器: </p><pre class="programlisting">public class MyLoadListener implements LoadEventListener { // this is the single method defined by the LoadEventListener interface public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType) throws HibernateException { if ( !MySecurity.isAuthorized( event.getEntityClassName(), event.getEntityId() ) ) { throw MySecurityException("Unauthorized access"); } }}</pre><p> 你还需要修改一处配置,来告诉Hibernate,除了默认的监听器,还要附加选定的监听器。 </p><pre class="programlisting"><hibernate-configuration> <session-factory> ... <event type="load"> <listener class="com.eg.MyLoadListener"/> <listener class="org.hibernate.event.def.DefaultLoadEventListener"/> </event> </session-factory></hibernate-configuration></pre><p> 看看用另一种方式,通过编程的方式来注册它。 </p><pre class="programlisting">Configuration cfg = new Configuration();LoadEventListener[] stack = { new MyLoadListener(), new DefaultLoadEventListener() };cfg.EventListeners().setLoadEventListeners(stack);</pre><p> 通过在XML配置文件声明而注册的监听器不能共享实例。如果在多个<tt class="literal"><listener/></tt>节点中使用 了相同的类的名字,则每一个引用都将会产生一个独立的实例。如果你需要在多个监听器类型之间共享 监听器的实例,则你必须使用编程的方式来进行注册。 </p><p> 为什么我们实现了特定监听器的接口,在注册的时候还要明确指出我们要注册哪个事件的监听器呢? 这是因为一个类可能实现多个监听器的接口。在注册的时候明确指定要监听的事件,可以让启用或者禁用对某个事件的监听的配置工作简单些。 </p></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="objectstate-decl-security"></a>12.3. Hibernate的声明式安全机制 </h2></div></div><div></div></div><p> 通常,Hibernate应用程序的声明式安全机制由会话外观层(session facade)所管理。 现在,Hibernate3允许某些特定的行为由JACC进行许可管理,由JAAS进行授权管理。 本功能是一个建立在事件框架之上的可选的功能。 </p><p> 首先,你必须要配置适当的事件监听器(event listener),来激活使用JAAS管理授权的功能。 </p><pre class="programlisting"><listener type="pre-delete" class="org.hibernate.secure.JACCPreDeleteEventListener"/><listener type="pre-update" class="org.hibernate.secure.JACCPreUpdateEventListener"/><listener type="pre-insert" class="org.hibernate.secure.JACCPreInsertEventListener"/><listener type="pre-load" class="org.hibernate.secure.JACCPreLoadEventListener"/></pre><p> 注意,<tt class="literal"><listener type="..." class="..."/></tt>只是<tt class="literal"><event type="..."><listener class="..."/></event></tt>的简写,对每一个事件类型都必须严格的有一个监听器与之对应。 </p><p> 接下来,仍然在<tt class="literal">hibernate.cfg.xml</tt>文件中,绑定角色的权限: </p><pre class="programlisting"><grant role="admin" entity-name="User" actions="insert,update,read"/><grant role="su" entity-name="User" actions="*"/></pre><p> 这些角色的名字就是你的JACC provider所定义的角色的名字。 </p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="transactions.html">上一页</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">上一级</a></td><td width="40%" align="right"> <a accesskey="n" href="batch.html">下一页</a></td></tr><tr><td width="40%" align="left" valign="top">第 11 章 事务和并发 </td><td width="20%" align="center"><a accesskey="h" href="index.html">起始页</a></td><td width="40%" align="right" valign="top"> 第 13 章 批量处理(Batch processing)</td></tr></table></div></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -