doc new 3.1 stuff
git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@7792 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
3ea2ac035f
commit
f1c2817dfe
|
@ -7,7 +7,7 @@
|
|||
functionality, and extension of Hibernate functionality.
|
||||
</para>
|
||||
|
||||
<sect1 id="objectstate-interceptors" revision="1">
|
||||
<sect1 id="objectstate-interceptors" revision="2">
|
||||
<title>Interceptors</title>
|
||||
|
||||
<para>
|
||||
|
@ -21,19 +21,26 @@
|
|||
updated.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You may either implement <literal>Interceptor</literal> directly or (better) extend
|
||||
<literal>EmptyInterceptor</literal>.
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[package org.hibernate.test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.Interceptor;
|
||||
import org.hibernate.EmptyInterceptor;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
public class AuditInterceptor implements Interceptor, Serializable {
|
||||
public class AuditInterceptor extends EmptyInterceptor {
|
||||
|
||||
private int updates;
|
||||
private int creates;
|
||||
private int loads;
|
||||
|
||||
public void onDelete(Object entity,
|
||||
Serializable id,
|
||||
|
@ -67,6 +74,9 @@ public class AuditInterceptor implements Interceptor, Serializable {
|
|||
Object[] state,
|
||||
String[] propertyNames,
|
||||
Type[] types) {
|
||||
if ( entity instanceof Auditable ) {
|
||||
loads++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -88,17 +98,15 @@ public class AuditInterceptor implements Interceptor, Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void postFlush(Iterator entities) {
|
||||
System.out.println("Creations: " + creates + ", Updates: " + updates);
|
||||
}
|
||||
|
||||
public void preFlush(Iterator entities) {
|
||||
public void afterTransactionCompletion(Transaction tx) {
|
||||
if ( tx.wasCommitted() ) {
|
||||
System.out.println("Creations: " + creates + ", Updates: " + updates, "Loads: " + loads);
|
||||
}
|
||||
updates=0;
|
||||
creates=0;
|
||||
loads=0;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
}]]></programlisting>
|
||||
|
||||
<para>
|
||||
|
@ -108,14 +116,15 @@ public class AuditInterceptor implements Interceptor, Serializable {
|
|||
<programlisting><![CDATA[Session session = sf.openSession( new AuditInterceptor() );]]></programlisting>
|
||||
|
||||
<para>
|
||||
You may also set an interceptor on a global level, using the <literal>Configuration</literal>:
|
||||
You may also set an interceptor on a global level, using the <literal>Configuration</literal>.
|
||||
In this case, the interceptor must be threadsafe.
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[new Configuration().setInterceptor( new AuditInterceptor() );]]></programlisting>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="objectstate-events" revision="2">
|
||||
<sect1 id="objectstate-events" revision="3">
|
||||
<title>Event system</title>
|
||||
|
||||
<para>
|
||||
|
@ -154,26 +163,28 @@ public class AuditInterceptor implements Interceptor, Serializable {
|
|||
example of a custom load event listener:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[public class MyLoadListener extends DefaultLoadEventListener {
|
||||
<programlisting><![CDATA[public class MyLoadListener implements LoadEventListener {
|
||||
// this is the single method defined by the LoadEventListener interface
|
||||
public Object onLoad(LoadEvent event, LoadEventListener.LoadType loadType)
|
||||
public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType)
|
||||
throws HibernateException {
|
||||
if ( !MySecurity.isAuthorized( event.getEntityClassName(), event.getEntityId() ) ) {
|
||||
throw MySecurityException("Unauthorized access");
|
||||
}
|
||||
return super.onLoad(event, loadType);
|
||||
}
|
||||
}]]></programlisting>
|
||||
|
||||
<para>
|
||||
You also need a configuration entry telling Hibernate to use the listener instead
|
||||
of the default listener:
|
||||
You also need a configuration entry telling Hibernate to use the listener in addition
|
||||
to the default listener:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[<hibernate-configuration>
|
||||
<session-factory>
|
||||
...
|
||||
<listener type="load" class="MyLoadListener"/>
|
||||
<event type="load">
|
||||
<listener class="com.eg.MyLoadListener"/>
|
||||
<listener class="org.hibernate.event.def.DefaultLoadEventListener"/>
|
||||
</event>
|
||||
</session-factory>
|
||||
</hibernate-configuration>]]></programlisting>
|
||||
|
||||
|
@ -182,7 +193,8 @@ public class AuditInterceptor implements Interceptor, Serializable {
|
|||
</para>
|
||||
|
||||
<programlisting><![CDATA[Configuration cfg = new Configuration();
|
||||
cfg.getSessionEventListenerConfig().setLoadEventListener( new MyLoadListener() );]]></programlisting>
|
||||
LoadEventListener[] stack = { new MyLoadListener(), new DefaultLoadEventListener() };
|
||||
cfg.EventListeners().setLoadEventListeners(stack);]]></programlisting>
|
||||
|
||||
<para>
|
||||
Listeners registered declaratively cannot share instances. If the same class name is
|
||||
|
@ -201,7 +213,7 @@ cfg.getSessionEventListenerConfig().setLoadEventListener( new MyLoadListener() )
|
|||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="objectstate-decl-security">
|
||||
<sect1 id="objectstate-decl-security" revision="2">
|
||||
<title>Hibernate declarative security</title>
|
||||
<para>
|
||||
Usually, declarative security in Hibernate applications is managed in a session facade
|
||||
|
@ -219,6 +231,12 @@ cfg.getSessionEventListenerConfig().setLoadEventListener( new MyLoadListener() )
|
|||
<listener type="pre-insert" class="org.hibernate.secure.JACCPreInsertEventListener"/>
|
||||
<listener type="pre-load" class="org.hibernate.secure.JACCPreLoadEventListener"/>]]></programlisting>
|
||||
|
||||
<para>
|
||||
Note that <literal><listener type="..." class="..."/></literal> is just a shorthand
|
||||
for <literal><event type="..."><listener class="..."/></event></literal>
|
||||
when there is exactly one listener for a particular event type.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Next, still in <literal>hibernate.cfg.xml</literal>, bind the permissions to roles:
|
||||
</para>
|
||||
|
|
|
@ -702,7 +702,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
|
|||
</tgroup>
|
||||
</table>
|
||||
|
||||
<sect2 id="performance-cache-mapping">
|
||||
<sect2 id="performance-cache-mapping" revision="2">
|
||||
<title>Cache mappings</title>
|
||||
|
||||
<para>
|
||||
|
@ -713,20 +713,39 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
|
|||
<programlistingco>
|
||||
<areaspec>
|
||||
<area id="cache1" coords="2 70"/>
|
||||
<area id="cache2" coords="3 70"/>
|
||||
<area id="cache3" coords="4 70"/>
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<cache
|
||||
usage="transactional|read-write|nonstrict-read-write|read-only"
|
||||
region="RegionName"
|
||||
include="all|non-lazy"
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="cache1">
|
||||
<para>
|
||||
<literal>usage</literal> specifies the caching strategy:
|
||||
<literal>usage</literal> (required) specifies the caching strategy:
|
||||
<literal>transactional</literal>,
|
||||
<literal>read-write</literal>,
|
||||
<literal>nonstrict-read-write</literal> or
|
||||
<literal>read-only</literal>
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="cache2">
|
||||
<para>
|
||||
<literal>region</literal> (optional, defaults to the class or
|
||||
collection role name) specifies the name of the second level cache
|
||||
region
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="cache3">
|
||||
<para>
|
||||
<literal>include</literal> (optional, defaults to <literal>all</literal>)
|
||||
<literal>non-lazy</literal> specifies that properties of the entity mapped
|
||||
with <literal>lazy="true"</literal> may not be cached when attribute-level
|
||||
lazy fetching is enabled
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
</programlistingco>
|
||||
|
||||
|
@ -1156,10 +1175,10 @@ hibernate.cache.use_structured_entries true]]></programlisting>
|
|||
</para>
|
||||
|
||||
<programlisting><![CDATA[Parent p = (Parent) sess.load(Parent.class, id);
|
||||
Child c = new Child();
|
||||
c.setParent(p);
|
||||
p.getChildren().add(c); //no need to fetch the collection!
|
||||
sess.flush();]]></programlisting>
|
||||
Child c = new Child();
|
||||
c.setParent(p);
|
||||
p.getChildren().add(c); //no need to fetch the collection!
|
||||
sess.flush();]]></programlisting>
|
||||
|
||||
</sect2>
|
||||
|
||||
|
|
|
@ -1022,7 +1022,8 @@ sess.find("from Cat as cat left outer join cat.kittens kitten");
|
|||
|
||||
// change to izi is not flushed!
|
||||
...
|
||||
tx.commit(); // flush occurs]]></programlisting>
|
||||
tx.commit(); // flush occurs
|
||||
sess.close();]]></programlisting>
|
||||
|
||||
<para>
|
||||
During flush, an exception might occur (e.g. if a DML operation violates a constraint).
|
||||
|
|
|
@ -380,7 +380,7 @@
|
|||
idiom looks like this:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[//Non-managed environment idiom
|
||||
<programlisting><![CDATA[// Non-managed environment idiom
|
||||
Session sess = factory.openSession();
|
||||
Transaction tx = null;
|
||||
try {
|
||||
|
@ -395,6 +395,30 @@ catch (RuntimeException e) {
|
|||
if (tx != null) tx.rollback();
|
||||
throw e; // or display error message
|
||||
}
|
||||
finally {
|
||||
sess.close();
|
||||
}]]></programlisting>
|
||||
|
||||
<para>
|
||||
Or even like this:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[// Non-managed environment idiom
|
||||
Session sess = factory.openSession();
|
||||
try {
|
||||
sess.getTransaction().begin();
|
||||
|
||||
// do some work
|
||||
...
|
||||
|
||||
sess.getTransaction().commit()
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
if ( sess.getTransaction().isActive() ) {
|
||||
sess.getTransaction().rollback();
|
||||
}
|
||||
throw e; // or display error message
|
||||
}
|
||||
finally {
|
||||
sess.close();
|
||||
}]]></programlisting>
|
||||
|
@ -461,6 +485,30 @@ catch (RuntimeException e) {
|
|||
if (tx != null) tx.rollback();
|
||||
throw e; // or display error message
|
||||
}
|
||||
finally {
|
||||
sess.close();
|
||||
}]]></programlisting>
|
||||
|
||||
<para>
|
||||
Or:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[// BMT idiom
|
||||
Session sess = factory.openSession();
|
||||
try {
|
||||
sess.getTransaction().begin();
|
||||
|
||||
// do some work
|
||||
...
|
||||
|
||||
sess.getTransaction().commit()
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
if ( sess.getTransaction().isActive() ) {
|
||||
sess.getTransaction().rollback();
|
||||
}
|
||||
throw e; // or display error message
|
||||
}
|
||||
finally {
|
||||
sess.close();
|
||||
}]]></programlisting>
|
||||
|
@ -601,6 +649,50 @@ Session sess = factory.getCurrentSession();
|
|||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2 id="transactions-demarcation-timeout">
|
||||
<title>Transaction timeout</title>
|
||||
|
||||
<para>
|
||||
One extremely important feature provided by a managed environment like EJB
|
||||
that is never provided for non-managed code is transaction timeout. Transaction
|
||||
timeouts ensure that no misbehaving transaction can indefinitely tie up
|
||||
resources while returning no response to the user. Outside a managed (JTA)
|
||||
environment, Hibernate cannot fully provide this functionality. However,
|
||||
Hibernate can at least control data access operations, ensuring that database
|
||||
level deadlocks and queries with huge result sets are limited by a defined
|
||||
timeout. In a managed environment, Hibernate can delegate transaction timeout
|
||||
to JTA. This functioanlity is abstracted by the Hibernate
|
||||
<literal>Transaction</literal> object.
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[
|
||||
Session sess = factory.openSession();
|
||||
try {
|
||||
//set transaction timeout to 3 seconds
|
||||
sess.getTransaction().setTimeout(3);
|
||||
sess.getTransaction().begin();
|
||||
|
||||
// do some work
|
||||
...
|
||||
|
||||
sess.getTransaction().commit()
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
if ( sess.getTransaction().isActive() ) {
|
||||
sess.getTransaction().rollback();
|
||||
}
|
||||
throw e; // or display error message
|
||||
}
|
||||
finally {
|
||||
sess.close();
|
||||
}]]></programlisting>
|
||||
|
||||
<para>
|
||||
Note that <literal>setTimeout()</literal> may not be called in a CMT bean,
|
||||
where transaction timeouts must be defined declaratively.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
|
|
Loading…
Reference in New Issue