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:
Gavin King 2005-08-10 04:54:55 +00:00
parent 3ea2ac035f
commit f1c2817dfe
4 changed files with 159 additions and 29 deletions

View File

@ -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>
@ -20,6 +20,11 @@
<literal>lastUpdateTimestamp</literal> property when an <literal>Auditable</literal> is
updated.
</para>
<para>
You may either implement <literal>Interceptor</literal> directly or (better) extend
<literal>EmptyInterceptor</literal>.
</para>
<programlisting><![CDATA[package org.hibernate.test;
@ -27,13 +32,15 @@ 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>&lt;listener type="..." class="..."/&gt;</literal> is just a shorthand
for <literal>&lt;event type="..."&gt;&lt;listener class="..."/&gt;&lt;/event&gt;</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>

View File

@ -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>

View File

@ -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).

View File

@ -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,9 +649,53 @@ 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>
</sect1>
<sect1 id="transactions-optimistic">