Author: epbernard
Date: 2007-02-07 17:08:01 -0500 (Wed, 07 Feb 2007)
New Revision: 11162
Removed:
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/lucene.xml
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/validator.xml
Modified:
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/master.xml
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/entity.xml
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/setup.xml
Log:
new Annotations documentation
Modified: branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/master.xml
===================================================================
--- branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/master.xml 2007-02-07
07:43:17 UTC (rev 11161)
+++ branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/master.xml 2007-02-07
22:08:01 UTC (rev 11162)
@@ -4,8 +4,7 @@
<!ENTITY setup SYSTEM "modules/setup.xml">
<!ENTITY entity SYSTEM "modules/entity.xml">
<!ENTITY xml-overriding SYSTEM "modules/xml-overriding.xml">
-<!ENTITY validator SYSTEM "modules/validator.xml">
-<!ENTITY lucene SYSTEM "modules/lucene.xml">
+<!ENTITY additionalmodules SYSTEM "modules/additionalmodules.xml">
]>
<book lang="en">
<bookinfo>
@@ -13,7 +12,7 @@
<subtitle>Reference Guide</subtitle>
- <releaseinfo>3.2.1.GA</releaseinfo>
+ <releaseinfo>3.2.2.GA</releaseinfo>
<mediaobject>
<imageobject>
@@ -63,8 +62,8 @@
informations.</para>
<para>If you are moving from previous Hibernate Annotations versions,
- please have a look at <
uri>http://www.hibernate.org/371.html</uri> for a
- migration guide.</para>
+ please have a look at <ulink
url="http://www.hibernate.org/398.html">Java
+ Persistence migration guide</ulink>.</para>
</preface>
&setup;
@@ -73,7 +72,6 @@
&xml-overriding;
- &validator;
+ &additionalmodules;
- &lucene;
</book>
\ No newline at end of file
Modified: branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/entity.xml
===================================================================
---
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2007-02-07
07:43:17 UTC (rev 11161)
+++
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/entity.xml 2007-02-07
22:08:01 UTC (rev 11162)
@@ -1,12 +1,12 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
<chapter id="entity">
<title>Entity Beans</title>
- <sect1 id="entity-overview" revision="1">
+ <sect1 id="entity-overview" revision="2">
<title>Intro</title>
- <para>This section covers EJB 3.0 (aka JPA) entity annotations and
- Hibernate-specific extensions.</para>
+ <para>This section covers EJB 3.0 (aka Java Persistence) entity
+ annotations and Hibernate-specific extensions.</para>
</sect1>
<sect1 id="entity-mapping" revision="2">
@@ -1203,11 +1203,11 @@
annotation takes into parameter a list of comma separated (target
entity) properties to order the collection by (eg <code>firstname
asc, age desc</code>), if the string is empty, the collection will
- be ordered by id. For true indexed
- collections, please refer to the <xref linkend="entity-hibspec"
/>.
- EJB3 allows you to map Maps using as a key one of the target entity
- property using
<literal>@MapKey(name="myProperty")</literal>
- (myProperty is a property name in the target entity). When using
+ be ordered by id. For true indexed collections, please refer to the
+ <xref linkend="entity-hibspec" />. EJB3 allows you to map Maps
using
+ as a key one of the target entity property using
+ <literal>@MapKey(name="myProperty")</literal> (myProperty
is a
+ property name in the target entity). When using
<literal>@MapKey</literal> (without property name), the target
entity primary key is used. The map key uses the same column as the
property pointed out: there is no additional column defined to hold
Deleted: branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/lucene.xml
===================================================================
---
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/lucene.xml 2007-02-07
07:43:17 UTC (rev 11161)
+++
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/lucene.xml 2007-02-07
22:08:01 UTC (rev 11162)
@@ -1,670 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<chapter id="lucene" revision="2">
- <title>Hibernate Search: Apache <trademark>Lucene</trademark>
- Integration</title>
-
- <para><ulink url="http://lucene.apache.org">Apache
Lucene</ulink> is a
- high-performance Java search engine library available at the Apache Software
- Foundation. Hibernate Annotations includes a package of annotations that
- allows you to mark any domain model object as indexable and have Hibernate
- maintain a Lucene index of any instances persisted via Hibernate. Apache
- Lucene is also integrated with the Hibernate query facility.</para>
-
- <para>Hibernate Search is a work in progress and new features are cooking in
- this area. So expect some compatibility changes in subsequent
- versions.</para>
-
- <section id="lucene-architecture">
- <title>Architecture</title>
-
- <para>Hibernate Search is made of an indexing engine and an index search
- engine. Both are backed by Apache Lucene.</para>
-
- <para>When an entity is inserted, updated or removed to/from the database,
- <productname>Hibernate Search</productname> will keep track of this
event
- (through the Hibernate event system) and schedule an index update. When
- out of transaction, the update is executed right after the actual database
- operation. It is however recommended, for both your database and Hibernate
- Search, to execute your operation in a transaction (whether JDBC or JTA).
- When in a transaction, the index update is schedule for the transaction
- commit (and discarded in case of transaction rollback). You can think of
- this as the regular (infamous) autocommit vs transactional behavior. From
- a performance perspective, the <emphasis>in transaction</emphasis> mode
is
- recommended. All the index updates are handled for you without you having
- to use the Apache Lucene APIs.</para>
-
- <para>To interact with Apache Lucene indexes, Hibernate Search has the
- notion of <classname>DirectoryProvider</classname>. A directory provider
- will manage a given Lucene <classname>Directory</classname> type. You
can
- configure directory providers to adjust the directory target.</para>
-
- <para><productname>Hibernate Search</productname> can also use a
Lucene
- index to search an entity and return a (list of) managed entity saving you
- from the tedious Object / Lucene Document mapping and low level Lucene
- APIs. The application code use the unified
- <classname>org.hibernate.Query</classname> API exactly the way a HQL or
- native query would be done.</para>
- </section>
-
- <section id="lucene-configuration">
- <title>Configuration</title>
-
- <section id="lucene-configuration-directory" revision="1">
- <title>Directory configuration</title>
-
- <para>Apache Lucene has a notion of Directory where the index is stored.
- The Directory implementation can be customized but Lucene comes bundled
- with a file system and a full memory implementation.
- <productname>Hibernate Search</productname> has the notion of
- <literal>DirectoryProvider</literal> that handle the configuration and
- the initialization of the Lucene Directory.</para>
-
- <table>
- <title>List of built-in Directory Providers</title>
-
- <tgroup cols="3">
- <thead>
- <row>
- <entry align="center">Class</entry>
-
- <entry align="center">description</entry>
-
- <entry align="center">Properties</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>org.hibernate.search.store.FSDirectoryProvider</entry>
-
- <entry>File system based directory. The directory used will be
-
&lt;indexBase&gt;/&lt;<literal>(a)Indexed.name</literal>&gt;</entry>
-
- <entry><literal>indexBase</literal>: Base
directory</entry>
- </row>
-
- <row>
- <entry>org.hibernate.search.store.RAMDirectoryProvider</entry>
-
- <entry>Memory based directory, the directory will be uniquely
- indentified by the <literal>(a)Indexed.name</literal>
- element</entry>
-
- <entry>none</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>If the built-in directory providers does not fit your needs, you
- can write your own directory provider by implementing the
- <classname>org.hibernate.store.DirectoryProvider</classname>
- interface</para>
-
- <para>Each indexed entity is associated to a Lucene index (an index can
- be shared by several entities but this is not usually the case). You can
- configure the index through properties prefixed by
-
<constant>hibernate.search.</constant><replaceable>indexname</replaceable>.
- Default properties inherited to all indexes can be defined using the
- prefix <constant>hibernate.search.default.</constant></para>
-
- <para>To define the directory provider of a given index, you use the
-
<constant>hibernate.search.<replaceable>indexname</replaceable>.directory_provider</constant></para>
-
- <programlisting>hibernate.search.default.directory_provider
org.hibernate.search.store.FSDirectoryProvider
-hibernate.search.default.indexBase=/usr/lucene/indexes
-
-hibernate.search.Rules.directory_provider
org.hibernate.search.store.RAMDirectoryProvider
-</programlisting>
-
- <para>applied on</para>
-
- <programlisting>@Indexed(name="Status")
-public class Status { ... }
-
-@Indexed(name="Rules")
-public class Rule { ... }</programlisting>
-
- <para>will create a file system directory in
- <filename>/usr/lucene/indexes/Status</filename> where the Status
- entities will be indexed, and use an in memory directory named
- <literal>Rules</literal> where Rule entities will be
indexed.</para>
-
- <para>So you can easily defined common rules like the directory provider
- and base directory, and overide those default later on on a per index
- basis.</para>
-
- <para>Writing your own <classname>DirectoryProvider</classname>,
you can
- benefit this configuration mechanism too.</para>
- </section>
-
- <section id="lucene-configuration-event" revision="1">
- <title>Enabling automatic indexing</title>
-
- <para>Finally, we enable the
<literal>SearchEventListener</literal> for
- the three Hibernate events that occur after changes are executed to the
- database.</para>
-
- <programlisting><hibernate-configuration>
- ...
- <event type="post-update"
- <listener
class="org.hibernate.search.event.FullTextIndexEventListener"/>
- </event>
- <event type="post-insert"
- <listener
class="org.hibernate.search.event.FullTextIndexEventListener"/>
- </event>
- <event type="post-delete"
- <listener
class="org.hibernate.search.event.FullTextIndexEventListener"/>
- </event>
-</hibernate-configuration></programlisting>
- </section>
- </section>
-
- <section id="lucene-mapping" revision="2">
- <title>Mapping entities to the index structure</title>
-
- <para>All the metadata information related to indexed entities is
- described through some Java annotations. There is no need for xml mapping
- files nor a list of indexed entities. The list is discovered at startup
- time scanning the Hibernate mapped entities.</para>
-
- <para>First, we must declare a persistent class as indexable. This is done
- by annotating the class with <literal>@Indexed</literal> (all entities
not
- annotated with <literal>@Indexed</literal> will be ignored by the
indexing
- process):</para>
-
- <programlisting>@Entity
-<emphasis
role="bold">@Indexed(index="indexes/essays")</emphasis>
-public class Essay {
- ...
-}</programlisting>
-
- <para>The <literal>index</literal> attribute tells Hibernate what
the
- Lucene directory name is (usually a directory on your file system). If you
- wish to define a base directory for all Lucene indexes, you can use the
- <literal>hibernate.search.default.indexBase</literal> property in your
- configuration file. Each entity instance will be represented by a Lucene
- <classname>Document</classname> inside the given index (aka
- Directory).</para>
-
- <para>For each property (or attribute) of your entity, you have the
- ability to describe how it will be indexed. The default (ie no annotation)
- means that the property is completly ignored by the indexing process.
- <literal>@Field</literal> does declare a property as indexed. When
- indexing an element to a Lucene document you can specify how it is
- indexed:</para>
-
- <itemizedlist>
- <listitem>
- <para><literal>name</literal>: describe under which name, the
property
- should be stored in the Lucene Document. The default value is the
- property name (following the JavaBeans convention)</para>
- </listitem>
-
- <listitem>
- <para><literal>store</literal>: describe whether or not the
property
- is stored in the Lucene index. You can store the value
- <literal>Store.YES</literal> (comsuming more space in the index),
- store it in a compressed way <literal>Store.COMPRESS</literal> (this
- does consume more CPU), or avoid any storage
- <literal>Store.NO</literal> (this is the default value). When a
- property is stored, you can retrieve it from the Lucene Document (note
- that this is not related to whether the element is indexed or
- not).</para>
- </listitem>
-
- <listitem>
- <para>index: describe how the element is indexed (ie the process used
- to index the property and the type of information store). The
- different values are <literal>Index.NO</literal> (no indexing, ie
- cannot be found by a query), <literal>Index.TOKENIZED</literal> (use
- an analyzer to process the property),
- <literal>Index.UN_TOKENISED</literal> (no analyzer pre processing),
- <literal>Index.NO_NORM</literal> (do not store the normalization
- data).</para>
- </listitem>
- </itemizedlist>
-
- <para>These attributes are part of the <literal>@Field</literal>
- annotation.</para>
-
- <para>Whether or not you want to store the data depends on how you wish to
- use the index query result. As of today, for a pure <productname>Hibernate
- Search</productname> usage, storing is not necessary. Whether or not you
- want to tokenize a property or not depends on whether you wish to search
- the element as is, or only normalized part of it. It make sense to
- tokenize a text field, but it does not to do it for a date field (or an id
- field).</para>
-
- <para>Finally, the id property of an entity is a special property used by
- <productname>Hibernate Search</productname> to ensure index unicity of a
- given entity. By design, an id has to be stored and must not be tokenized.
- To mark a property as index id, use the <literal>@DocumentId</literal>
- annotation.</para>
-
- <programlisting>@Entity
-@Indexed(index="indexes/essays")
-public class Essay {
- ...
-
- @Id
- <emphasis role="bold">@DocumentId</emphasis>
- public Long getId() { return id; }
-
- <emphasis role="bold">@Field(name="Abstract",
index=Index.TOKENIZED, store=Store.YES)</emphasis>
- public String getSummary() { return summary; }
-
- @Lob
- <emphasis role="bold">(a)Field(index=Index.TOKENIZED)</emphasis>
- public String getText() { return text; }
-
-}</programlisting>
-
- <para>These annotations define an index with three fields:
- <literal>id</literal>, <literal>Abstract</literal> and
- <literal>text</literal>. Note that by default the field name is
- decapitalized, following the JavaBean specification.</para>
-
- <para>Note: you <emphasis>must</emphasis> specify
- <literal>@DocumentId</literal> on the identifier property of your entity
- class.</para>
-
- <para>Lucene has the notion of <emphasis>boost factor</emphasis>.
It's a
- way to give more weigth to a field or to an indexed element over an other
- during the indexation process. You can use <literal>@Boost</literal> at
- the field or the class level.</para>
-
- <programlisting>@Entity
-@Indexed(index="indexes/essays")
-<emphasis role="bold">@Boost(2)</emphasis>
-public class Essay {
- ...
-
- @Id
- @DocumentId
- public Long getId() { return id; }
-
- @Field(name="Abstract", index=Index.TOKENIZED, store=Store.YES)
- <emphasis role="bold">(a)Boost(2.5f)</emphasis>
- public String getSummary() { return summary; }
-
- @Lob
- @Field(index=Index.TOKENIZED)
- public String getText() { return text; }
-
-}</programlisting>
-
- <para>In our example, Essay's probability to reach the top of the search
- list will be multiplied by 2 and the summary field will be 2.5 more
- important than the test field. Note that this explaination is actually
- wrong, but it is simple and close enought to the reality. Please check the
- Lucene documentation or the excellent <citetitle>Lucene In
- Action</citetitle> from Otis Gospodnetic and Erik Hatcher.</para>
-
- <para>The analyzer class used to index the elements is configurable
- through the <literal>hibernate.search.analyzer</literal> property. If
none
- defined,
-
<classname>org.apache.lucene.analysis.standard.StandardAnalyzer</classname>
- is used as the default.</para>
- </section>
-
- <section id="lucene-bridge">
- <title>Property/Field Bridge</title>
-
- <para>All field of a full text index in Lucene have to be represented as
- Strings. Ones Java properties have to be indexed in a String form. For
- most of your properties, <productname>Hibernate Search</productname>
does
- the translation job for you thanks to a built-in set of bridges. In some
- cases, though you need a fine grain control over the translation
- process.</para>
-
- <section>
- <title>Built-in bridges</title>
-
- <para><literal>Hibernate Search</literal> comes bundled with a
set of
- built-in bridges between a Java property type and its full text
- representation.</para>
-
- <para><literal>Null</literal> elements are not indexed (Lucene
does not
- support null elements and it does not make much sense either)</para>
-
- <variablelist>
- <varlistentry>
- <term>null</term>
-
- <listitem>
- <para>null elements are not indexed. Lucene does not support null
- elements and this does not make much sense either.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>java.lang.String</term>
-
- <listitem>
- <para>String are indexed as is</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>short, Short, integer, Integer, long, Long, float, Float,
- double, Double, BigInteger, BigDecimal</term>
-
- <listitem>
- <para>Numbers are converted in their String representation. Note
- that numbers cannot be compared by Lucene (ie used in ranged
- queries) out of the box: they have to be padded <footnote>
- <para>Using a Range query is debattable and has drawbacks, an
- alternative approach is to use a Filter query which will
- filter the result query to the appropriate range.</para>
-
- <para><productname>Hibernate Search</productname> will
support
- a padding mechanism</para>
- </footnote></para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>java.util.Date</term>
-
- <listitem>
- <para>Dates are stored as yyyyMMddHHmmssSSS in GMT time
- (200611072203012 for Nov 7th of 2006 4:03PM and 12ms EST). You
- shouldn't really bother with the internal format. What is
- important is that when using a DateRange Query, you should know
- that the dates have to be expressed in GMT time.</para>
-
- <para>Usually, storing the date up to the milisecond is not
- necessary. <literal>@DateBridge</literal> defines the
appropriate
- resolution you are willing to store in the index
-
(<literal><literal>(a)DateBridge(resolution=Resolution.DAY)</literal></literal>).
- The date pattern will then be truncated accordingly.</para>
-
- <programlisting>@Entity @Indexed
-public class Meeting {
- @Field(index=Index.UN_TOKENIZED)
- <emphasis
role="bold">(a)DateBridge(resolution=Resolution.MINUTE)</emphasis>
- private Date date;
- ...
-}</programlisting>
-
- <warning>
- <para>A Date whose resolution is lower than
- <literal>MILLISECOND</literal> cannot be a
- <literal>@DocumentId</literal></para>
- </warning>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para></para>
- </section>
-
- <section>
- <title>Custom Bridge</title>
-
- <para>It can happen that the built-in bridges of Hibernate Search does
- not cover some of your property types, or that the String representation
- used is not what you expect.</para>
-
- <section>
- <title>StringBridge</title>
-
- <para>The simpliest custom solution is to give
<productname>Hibernate
- Search</productname> an implementation of your expected
- <emphasis>object to String</emphasis> bridge. To do so you need to
- implements the
- <literal>org.hibernate.search.bridge.StringBridge</literal>
- interface</para>
-
- <programlisting>/**
- * Padding Integer bridge.
- * All numbers will be padded with 0 to match 5 digits
- *
- * @author Emmanuel Bernard
- */
-public class PaddedIntegerBridge implements <emphasis
role="bold">StringBridge</emphasis> {
-
- private int PADDING = 5;
-
- <emphasis role="bold">public String objectToString(Object
object)</emphasis> {
- String rawInteger = ( (Integer) object ).toString();
- if (rawInteger.length() > PADDING) throw new IllegalArgumentException(
"Try to pad on a number too big" );
- StringBuilder paddedInteger = new StringBuilder( );
- for ( int padIndex = rawInteger.length() ; padIndex < PADDING ; padIndex++
) {
- paddedInteger.append('0');
- }
- return paddedInteger.append( rawInteger ).toString();
- }
-}</programlisting>
-
- <para>Then any property or field can use this bridge thanks to the
- <literal>@FieldBridge</literal> annotation</para>
-
- <programlisting><emphasis role="bold">@FieldBridge(impl =
PaddedIntegerBridge.class)</emphasis>
-private Integer length;</programlisting>
-
- <para>Parameters can be passed to the Bridge implementation making it
- more flexible. The Bridge implementation implements a
- <classname>ParameterizedBridge</classname> interface, and the
- parameters are passed through the <literal>@FieldBridge</literal>
- annotation.</para>
-
- <programlisting>public class PaddedIntegerBridge implements StringBridge,
<emphasis
- role="bold">ParameterizedBridge</emphasis> {
-
- public static String PADDING_PROPERTY = "padding";
- private int padding = 5; //default
-
- <emphasis role="bold">public void setParameterValues(Map
parameters)</emphasis> {
- Object padding = parameters.get( PADDING_PROPERTY );
- if (padding != null) this.padding = (Integer) padding;
- }
-
- public String objectToString(Object object) {
- String rawInteger = ( (Integer) object ).toString();
- if (rawInteger.length() > padding) throw new IllegalArgumentException(
"Try to pad on a number too big" );
- StringBuilder paddedInteger = new StringBuilder( );
- for ( int padIndex = rawInteger.length() ; padIndex < padding ; padIndex++
) {
- paddedInteger.append('0');
- }
- return paddedInteger.append( rawInteger ).toString();
- }
-}
-
-
-//property
-@FieldBridge(impl = PaddedIntegerBridge.class,
- <emphasis role="bold">params =
@Parameter(name="padding", value="10")</emphasis> )
-private Integer length;</programlisting>
-
- <para>The <classname>ParameterizedBridge</classname> interface
can be
- implemented by <classname>StringBridge</classname>,
- <classname>TwoWayStringBridge</classname>,
- <classname>FieldBridge</classname> implementations (see
- bellow).</para>
-
- <para>If you expect to use your bridge implementation on for an id
- property (ie annotated with <literal>@DocumentId</literal>), you
need
- to use a slightly extended version of
<literal>StringBridge</literal>
- named <classname>TwoWayStringBridge</classname>.
<literal>Hibernate
- Search</literal> needs to read the string representation of the
- identifier and generate the object out of it. There is not difference
- in the way the <literal>@FieldBridge</literal> annotation is
- used.</para>
-
- <programlisting>public class PaddedIntegerBridge implements
TwoWayStringBridge, ParameterizedBridge {
-
- public static String PADDING_PROPERTY = "padding";
- private int padding = 5; //default
-
- public void setParameterValues(Map parameters) {
- Object padding = parameters.get( PADDING_PROPERTY );
- if (padding != null) this.padding = (Integer) padding;
- }
-
- public String objectToString(Object object) {
- String rawInteger = ( (Integer) object ).toString();
- if (rawInteger.length() > padding) throw new IllegalArgumentException(
"Try to pad on a number too big" );
- StringBuilder paddedInteger = new StringBuilder( );
- for ( int padIndex = rawInteger.length() ; padIndex < padding ; padIndex++
) {
- paddedInteger.append('0');
- }
- return paddedInteger.append( rawInteger ).toString();
- }
-
- <emphasis role="bold">public Object stringToObject(String
stringValue)</emphasis> {
- return new Integer(stringValue);
- }
-}
-
-
-//id property
-@DocumentId
-@FieldBridge(impl = PaddedIntegerBridge.class,
- params = @Parameter(name="padding", value="10") )
-private Integer id;</programlisting>
-
- <para>It is critically important for the two-way process to be
- idempotent (ie object = stringToObject( objectToString( object ) )
- ).</para>
- </section>
-
- <section>
- <title>FieldBridge</title>
-
- <para>Some usecase requires more than a simple object to string
- translation when mapping a property to a Lucene index. To give you
- most of the flexibility you can also implement a bridge as a
- <classname>FieldBridge</classname>. This interface give you a
property
- value and let you map it the way you want in your Lucene
- <classname>Document</classname>.This interface is very similar in
its
- concept to the <productname>Hibernate</productname>
- <classname>UserType</classname>.</para>
-
- <para>You can for example store a given property in two different
- document fields</para>
-
- <programlisting>/**
- * Store the date in 3 different field year, month, day
- * to ease Range Query per year, month or day
- * (eg get all the elements of december for the last 5 years)
- *
- * @author Emmanuel Bernard
- */
-public class DateSplitBridge implements FieldBridge {
- private final static TimeZone GMT = TimeZone.getTimeZone("GMT");
-
- <emphasis role="bold">public void set(String name, Object value,
Document document, Field.Store store, Field.Index index, Float boost) {</emphasis>
- Date date = (Date) value;
- Calendar cal = GregorianCalendar.getInstance( GMT );
- cal.setTime( date );
- int year = cal.get( Calendar.YEAR );
- int month = cal.get( Calendar.MONTH ) + 1;
- int day = cal.get( Calendar.DAY_OF_MONTH );
- //set year
- Field field = new Field( name + ".year", String.valueOf(year), store,
index );
- if ( boost != null ) field.setBoost( boost );
- document.add( field );
- //set month and pad it if needed
- field = new Field( name + ".month", month < 10 ? "0" :
"" + String.valueOf(month), store, index );
- if ( boost != null ) field.setBoost( boost );
- document.add( field );
- //set day and pad it if needed
- field = new Field( name + ".day", day < 10 ? "0" :
"" + String.valueOf(day), store, index );
- if ( boost != null ) field.setBoost( boost );
- document.add( field );
- }
-}
-
-
-//property
-<emphasis role="bold">@FieldBridge(impl =
DateSplitBridge.class)</emphasis>
-private Integer length;</programlisting>
-
- <para></para>
- </section>
- </section>
- </section>
-
- <section id="lucene-query">
- <title>Querying</title>
-
- <para>The second most important capability of <productname>Hibernate
- Search</productname> is the ability to execute a Lucene query and retrieve
- entities managed by an Hibernate session, providing the power of Lucene
- without living the Hibernate paradygm, and giving another dimension to the
- Hibernate classic search mechanisms (HQL, Criteria query, native SQL
- query).</para>
-
- <para>To access the <productname>Hibernate Search</productname>
querying
- facilities, you have to use an Hibernate
- <classname>FullTextSession</classname>. A SearchSession wrap an regular
- <classname>org.hibernate.Session</classname> to provide query and
indexing
- capabilities.</para>
-
- <programlisting>Session session = sessionFactory.openSession();
-...
-FullTextSession fullTextSession =
Search.createFullTextSession(session);</programlisting>
-
- <para>The search facility is built on native Lucene queries.</para>
-
- <programlisting>org.apache.lucene.QueryParser parser = new
QueryParser("title", new StopAnalyzer() );
-
-org.hibernate.lucene.search.Query luceneQuery = parser.parse( "summary:Festina Or
brand:Seiko" );
-<emphasis role="bold">org.hibernate.Query fullTextQuery =
fullTextSession.createFullTextQuery( luceneQuery );</emphasis>
-
-List result = fullTextQuery.list(); //return a list of managed
objects</programlisting>
-
- <para>The Hibernate query built on top of the Lucene query is a regular
- <literal>org.hibernate.Query</literal>, you are is the same paradygm as
- the other Hibernate query facilities (HQL, Native or Criteria). The
- regular <literal>list()</literal>,
<literal>uniqueResult()</literal>,
- <literal>iterate()</literal> and <literal>scroll()</literal>
can be
- used.</para>
-
- <para>If you expect a reasonnable result number and expect to work on all
- of them, <methodname>list()</methodname> or
- <methodname>uniqueResult()</methodname> are recommanded.
- <methodname>list()</methodname> work best if the entity
- <literal>batch-size</literal> is set up properly. Note that Hibernate
- Seach has to process all Lucene Hits elements when using
- <methodname>list()</methodname>,
<methodname>uniqueResult()</methodname>
- and <methodname>iterate()</methodname>. If you wish to minimize Lucene
- document loading, <methodname>scroll()</methodname> is more appropriate,
- Don't forget to close the <classname>ScrollableResults</classname>
object
- when you're done, since it keeps Lucene resources.</para>
-
- <para>An efficient way to work with queries is to use pagination. The
- pagination API is exactly the one available in
- <classname>org.hibernate.Query</classname>:</para>
-
- <programlisting><emphasis role="bold">org.hibernate.Query
fullTextQuery = fullTextSession.createFullTextQuery( luceneQuery );</emphasis>
-fullTextQuery.setFirstResult(30);
-fullTextQuery.setMaxResult(20);
-fullTextQuery.list(); //will return a list of 20 elements starting from the
30th</programlisting>
-
- <para>Only the relevant Lucene Documents are accessed.</para>
- </section>
-
- <section id="lucene-index">
- <title>Indexing</title>
-
- <para>It is sometimes useful to index an object event if this object is
- not inserted nor updated to the database. This is especially true when you
- want to build your index the first time. You can achieve that goal using
- the <classname>FullTextSession</classname>.</para>
-
- <programlisting>FullTextSession fullTextSession =
Search.createFullTextSession(session);
-Transaction tx = fullTextSession.beginTransaction();
-for (Customer customer : customers) {
- <emphasis
role="bold">fullTextSession.index(customer);</emphasis>
-}
-tx.commit(); //index are written at commit time</programlisting>
-
- <para>For maximum efficiency, Hibernate Search batch index operations
- which and execute them at commit time (Note: you don't need to use
- <classname>org.hibernate.Transaction</classname> in a JTA
- environment).</para>
- </section>
-</chapter>
\ No newline at end of file
Modified: branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/setup.xml
===================================================================
--- branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/setup.xml 2007-02-07
07:43:17 UTC (rev 11161)
+++ branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/setup.xml 2007-02-07
22:08:01 UTC (rev 11162)
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
<chapter>
<title id="setup" revision="1">Setting up an annotations
project</title>
- <section id="setup-requirements">
+ <section id="setup-requirements" revision="1">
<title>Requirements</title>
<itemizedlist>
@@ -12,27 +12,27 @@
</listitem>
<listitem>
- <para><emphasis>This release requires Hibernate 3.2.0.GA and above.
- Do not use this release of Hibernate Annotations with an older version
- of Hibernate 3.x!</emphasis></para>
+ <para><emphasis>This release requires Hibernate 3.2.0.GA and above.
Do
+ not use this release of Hibernate Annotations with an older version of
+ Hibernate 3.x!</emphasis></para>
</listitem>
<listitem>
- <para>This release is known to work on Hibernate core 3.2.0.CR5, 3.2.0.GA
- and 3.2.1.GA</para>
+ <para>This release is known to work on Hibernate core 3.2.0.CR5 and
+ 3.2.x.GA</para>
</listitem>
<listitem>
- <para>Make sure you have JDK 5.0 installed. You can of course continue
- using XDoclet and get some of the benefits of annotation-based
- metadata with older JDK versions. Note that this document only
- describes JDK 5.0 annotations and you have to refer to the XDoclet
- documentation for more information.</para>
+ <para>Make sure you have JDK 5.0 installed or above. You can of course
+ continue using XDoclet and get some of the benefits of
+ annotation-based metadata with older JDK versions. Note that this
+ document only describes JDK 5.0 annotations and you have to refer to
+ the XDoclet documentation for more information.</para>
</listitem>
</itemizedlist>
</section>
- <section id="setup-configuration">
+ <section id="setup-configuration" revision="1">
<title>Configuration</title>
<para>First, set up your classpath (after you have created a new project
@@ -43,17 +43,23 @@
</listitem>
<listitem>
- <para>Copy <filename>hibernate-annotations.jar</filename>
and
+ <para>Copy <filename>hibernate-annotations.jar</filename>,
+ <filename>lib/hibernate-comons-annotations.jar</filename> and
<filename>lib/ejb3-persistence.jar</filename> from the Hibernate
Annotations distribution to your classpath as well.</para>
</listitem>
- <listitem>
- <para>To use the <xref linkend="lucene" />, add the
lucene jar
- file.</para>
- </listitem>
</itemizedlist></para>
+ <para>If you wish to use Hibernate Validator (TODO make a link to HV doc),
+ download it from the Hibernate website and add
+ <filename>hibernate-validator.jar</filename> in your
classpath.</para>
+
+ <para>If you wish to use Hibernate Search (TODO make a link to HSearch
+ doc), download it from the Hibernate website and add
+ <filename>hibernate-search.jar</filename> and
+ <filename>lucene-core-x.y.z.jar</filename> in your
classpath.</para>
+
<para>We also recommend a small wrapper class to startup Hibernate in a
static initializer block, known as <classname>HibernateUtil</classname>.
You might have seen this class in various forms in other areas of the
Deleted: branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/validator.xml
===================================================================
---
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/validator.xml 2007-02-07
07:43:17 UTC (rev 11161)
+++
branches/HAN_SPLIT/HibernateExt/metadata/doc/reference/en/modules/validator.xml 2007-02-07
22:08:01 UTC (rev 11162)
@@ -1,560 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<chapter id="validator">
- <title>Hibernate Validator</title>
-
- <para>Annotations are a very convenient and elegant way to specify invariant
- constraints for a domain model. You can, for example, express that a
- property should never be null, that the account balance should be strictly
- positive, etc. These domain model constraints are declared in the bean
- itself by annotating its properties. A validator can then read them and
- check for constraint violations. The validation mechanism can be executed in
- different layers in your application without having to duplicate any of
- these rules (presentation layer, data access layer). Hibernate Validator has
- been designed for that purpose.</para>
-
- <para>Hibernate Validator works at two levels. First, it is able to check
- in-memory instances of a class for constraint violations. Second, it can
- apply the constraints to the Hibernate metamodel and incorporate them into
- the generated database schema.</para>
-
- <para>Each constraint annotation is associated to a validator implementation
- responsible for checking the constraint on the entity instance. A validator
- can also (optionally) apply the constraint to the Hibernate metamodel,
- allowing Hibernate to generate DDL that expresses the constraint. With the
- appropriate event listener, you can execute the checking operation on
- inserts and updates done by Hibernate. Hibernate Validator is not limited to
- use with Hibernate. You can easily use it anywhere in your
- application.</para>
-
- <para>When checking instances at runtime, Hibernate Validator returns
- information about constraint violations in an array of
- <classname>InvalidValue</classname>s. Among other information, the
- <classname>InvalidValue</classname> contains an error description message
- that can embed the parameter values bundle with the annotation (eg. length
- limit), and message strings that may be externalized to a
- <classname>ResourceBundle</classname>.</para>
-
- <sect1 id="validator-constraints">
- <title>Constraints</title>
-
- <sect2>
- <title>What is a constraint?</title>
-
- <para>A constraint is represented by an annotation. A constraint usually
- has some attributes used to parameterize the constraints limits. The
- constraint apply to the annotated element.</para>
- </sect2>
-
- <sect2 id="validator-constraints-built-in" revision="1">
- <title>Built in constraints</title>
-
- <para>Hibernate Validator comes with some built-in constraints, which
- covers most basic data checks. As we'll see later, you're not limited to
- them, you can in a minute write your own constraints.</para>
-
- <table>
- <title>Built-in constraints</title>
-
- <tgroup cols="4">
- <colspec align="center" />
-
- <thead>
- <row>
- <entry>Annotation</entry>
-
- <entry>Apply on</entry>
-
- <entry>Runtime checking</entry>
-
- <entry>Hibernate Metadata impact</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>@Length(min=, max=)</entry>
-
- <entry>property (String)</entry>
-
- <entry>check if the string length match the range</entry>
-
- <entry>Column length will be set to max</entry>
- </row>
-
- <row>
- <entry>@Max(value=)</entry>
-
- <entry>property (numeric or string representation of a
- numeric)</entry>
-
- <entry>check if the value is less than or equals to
max</entry>
-
- <entry>Add a check constraint on the column</entry>
- </row>
-
- <row>
- <entry>@Min(value=)</entry>
-
- <entry>property (numeric or string representation of a
- numeric)</entry>
-
- <entry>check if the value is more than or equals to
min</entry>
-
- <entry>Add a check constraint on the column</entry>
- </row>
-
- <row>
- <entry>@NotNull</entry>
-
- <entry>property</entry>
-
- <entry>check if the value is not null</entry>
-
- <entry>Column(s) are not null</entry>
- </row>
-
- <row>
- <entry>@NotEmpty</entry>
-
- <entry>property</entry>
-
- <entry>check if the string is not null nor empty. Check if the
- connection is not null nor empty</entry>
-
- <entry>Column(s) are not null (for String)</entry>
- </row>
-
- <row>
- <entry>@Past</entry>
-
- <entry>property (date or calendar)</entry>
-
- <entry>check if the date is in the past</entry>
-
- <entry>Add a check constraint on the column</entry>
- </row>
-
- <row>
- <entry>@Future</entry>
-
- <entry>property (date or calendar)</entry>
-
- <entry>check if the date is in the future</entry>
-
- <entry>none</entry>
- </row>
-
- <row>
- <entry>@Pattern(regex="regexp", flag=)</entry>
-
- <entry>property (string)</entry>
-
- <entry>check if the property match the regular expression given
- a match flag (see <classname> java.util.regex.Pattern
- </classname> )</entry>
-
- <entry>none</entry>
- </row>
-
- <row>
- <entry>@Range(min=, max=)</entry>
-
- <entry>property (numeric or string representation of a
- numeric)</entry>
-
- <entry>check if the value is between min and max
- (included)</entry>
-
- <entry>Add a check constraint on the column</entry>
- </row>
-
- <row>
- <entry>@Size(min=, max=)</entry>
-
- <entry>property (array, collection, map)</entry>
-
- <entry>check if the element size is between min and max
- (included)</entry>
-
- <entry>none</entry>
- </row>
-
- <row>
- <entry>@AssertFalse</entry>
-
- <entry>property</entry>
-
- <entry>check that the method evaluates to false (useful for
- constraints expressed in code rather than annotations)</entry>
-
- <entry>none</entry>
- </row>
-
- <row>
- <entry>@AssertTrue</entry>
-
- <entry>property</entry>
-
- <entry>check that the method evaluates to true (useful for
- constraints expressed in code rather than annotations)</entry>
-
- <entry>none</entry>
- </row>
-
- <row>
- <entry>@Valid</entry>
-
- <entry>property (object)</entry>
-
- <entry>perform validation recursively on the associated object.
- If the object is a Collection or an array, the elements are
- validated recursively. If the object is a Map, the value
- elements are validated recursively.</entry>
-
- <entry>none</entry>
- </row>
-
- <row>
- <entry>@Email</entry>
-
- <entry>property (String)</entry>
-
- <entry>check whether the string is conform to the email address
- specification</entry>
-
- <entry>none</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </sect2>
-
- <sect2 id="validator-constraints-error" xreflabel="Error
messages">
- <title>Error messages</title>
-
- <para>Hibernate Validator comes with a default set of error messages
- translated in about ten languages (if yours is not part of it, please
- sent us a patch). You can override those messages by creating a
- <filename>ValidatorMessages.properties</filename> or
- (<filename>ValidatorMessages_loc.properties</filename>) and override
the
- needed keys. You can even add your own additional set of messages while
- writing your validator annotations. If Hibernate Validator cannot
- resolve a key from your resourceBundle nor from ValidatorMessage, it
- falls back to the default built-in values.</para>
-
- <para>Alternatively you can provide a
- <classname>ResourceBundle</classname> while checking programmatically
- the validation rules on a bean or if you want a completly different
- interpolation mechanism, you can provide an implementation of
- <literal>org.hibernate.validator.MessageInterpolator</literal> (check
- the JavaDoc for more informations).</para>
- </sect2>
-
- <sect2>
- <title>Writing your own constraints</title>
-
- <para>Extending the set of built-in constraints is extremely easy. Any
- constraint consists of two pieces: the constraint
- <emphasis>descriptor</emphasis> (the annotation) and the constraint
- <emphasis>validator</emphasis> (the implementation class). Here is a
- simple user-defined descriptor:</para>
-
- <programlisting>(a)ValidatorClass(CapitalizedValidator.class)
-@Target(METHOD)
-@Retention(RUNTIME)
-@Documented
-public @interface Capitalized {
- CapitalizeType type() default Capitalize.FIRST;
- String message() default "has incorrect capitalization";
-}</programlisting>
-
- <para><literal>type</literal> is a parameter describing how the
property
- should to be capitalized. This is a user parameter fully dependant on
- the annotation business.</para>
-
- <para><literal>message</literal> is the default string used to
describe
- the constraint violation and is mandatory. You can hard code the string
- or you can externalize part/all of it through the Java ResourceBundle
- mechanism. Parameters values are going to be injected inside the message
- when the <literal>{parameter}</literal> string is found (in our
example
- <literal>Capitalization is not {type}</literal> would generate
- <literal>Capitalization is not FIRST</literal>), externalizing the
whole
- string in <filename>ValidatorMessages.properties</filename> is
- considered good practice. See <xref
- linkend="validator-constraints-error" />.</para>
-
- <programlisting>(a)ValidatorClass(CapitalizedValidator.class)
-@Target(METHOD)
-@Retention(RUNTIME)
-@Documented
-public @interface Capitalized {
- CapitalizeType type() default Capitalize.FIRST;
- String message() default "{validator.capitalized}";
-}
-
-...
-#in ValidatorMessages.properties
-validator.capitalized=<literal>Capitalization is not
{type}</literal></programlisting>
-
- <para>As you can see the {} notation is recursive.</para>
-
- <para>To link a descriptor to its validator implementation, we use the
- <literal>@ValidatorClass</literal> meta-annotation. The validator
class
- parameter must name a class which implements
-
<literal>Validator<ConstraintAnnotation></literal>.</para>
-
- <para>We now have to implement the validator (ie. the rule checking
- implementation). A validation implementation can check the value of the
- a property (by implementing <literal>PropertyConstraint</literal>)
- and/or can modify the hibernate mapping metadata to express the
- constraint at the database level (by implementing
- <literal>PersistentClassConstraint</literal>).</para>
-
- <programlisting>public class CapitalizedValidator
- implements Validator<Capitalized>, PropertyConstraint {
- private CapitalizeType type;
-
- //part of the Validator<Annotation> contract,
- //allows to get and use the annotation values
- public void initialize(Capitalized parameters) {
- type = parameters.type();
- }
-
- //part of the property constraint contract
- public boolean isValid(Object value) {
- if (value==null) return true;
- if ( !(value instanceof String) ) return false;
- String string = (String) value;
- if (type == CapitalizeType.ALL) {
- return string.equals( string.toUpperCase() );
- }
- else {
- String first = string.substring(0,1);
- return first.equals( first.toUpperCase();
- }
- }
-}</programlisting>
-
- <para>The <literal>isValid()</literal> method should return false
if the
- constraint has been violated. For more examples, refer to the built-in
- validator implementations.</para>
-
- <para>We only have seen property level validation, but you can write a
- Bean level validation annotation. Instead of receiving the return
- instance of a property, the bean itself will be passed to the validator.
- To activate the validation checking, just annotated the bean itself
- instead. A small sample can be found in the unit test suite.</para>
- </sect2>
-
- <sect2>
- <title>Annotating your domain model</title>
-
- <para>Since you are already familiar with annotations now, the syntax
- should be very familiar.</para>
-
- <programlisting>public class Address {
- private String line1;
- private String line2;
- private String zip;
- private String state;
- private String country;
- private long id;
-
- // a not null string of 20 characters maximum
- @Length(max=20)
- @NotNull
- public String getCountry() {
- return country;
- }
-
- // a non null string
- @NotNull
- public String getLine1() {
- return line1;
- }
-
- //no constraint
- public String getLine2() {
- return line2;
- }
-
- // a not null string of 3 characters maximum
- @Length(max=3) @NotNull
- public String getState() {
- return state;
- }
-
- // a not null numeric string of 5 characters maximum
- // if the string is longer, the message will
- //be searched in the resource bundle at key 'long'
- @Length(max=5, message="{long}")
- @Pattern(regex="[0-9]+")
- @NotNull
- public String getZip() {
- return zip;
- }
-
- // should always be true
- @AssertTrue
- public boolean isValid() {
- return true;
- }
-
- // a numeric between 1 and 2000
- @Id @Min(1)
- @Range(max=2000)
- public long getId() {
- return id;
- }
-}</programlisting>
-
- <para>While the example only shows public property validation, you can
- also annotate fields of any kind of visibility.</para>
-
- <programlisting>@MyBeanConstraint(max=45)
-public class Dog {
- @AssertTrue private boolean isMale;
- @NotNull protected String getName() { ... };
- ...
-}</programlisting>
-
- <para>You can also annotate interfaces. Hibernate Validator will check
- all superclasses and interfaces extended or implemented by a given bean
- to read the appropriate validator annotations.</para>
-
- <programlisting>public interface Named {
- @NotNull String getName();
- ...
-}
-
-public class Dog implements Named {
-
- @AssertTrue private boolean isMale;
-
- public String getName() { ... };
-
-}</programlisting>
-
- <para>The name property will be checked for nullity when the Dog bean is
- validated.</para>
- </sect2>
- </sect1>
-
- <sect1>
- <title>Using the Validator framework</title>
-
- <para>Hibernate Validator is intended to be used to implement
- multi-layered data validation, where we express constraints in one place
- (the annotated domain model) and apply them at various different layers of
- the application.</para>
-
- <sect2>
- <title>Database schema-level validation</title>
-
- <para>Out of the box, Hibernate Annotations will translate the
- constraints you have defined for your entities into mapping metadata.
- For example, if a property of your entity is annotated
- <literal>@NotNull</literal>, its columns will be declared as
- <literal>not null</literal> in the DDL schema generated by
- Hibernate.</para>
- </sect2>
-
- <sect2>
- <title>Hibernate event-based validation</title>
-
- <para>Hibernate Validator has two built-in Hibernate event listeners.
- Whenever a <literal>PreInsertEvent</literal> or
- <literal>PreUpdateEvent</literal> occurs, the listeners will verify
all
- constraints of the entity instance and throw an exception if any
- constraint is violated. Basically, objects will be checked before any
- inserts and before any updates made by Hibernate. This is the most
- convenient and the easiest way to activate the validation process. On
- constraint violation, the event will raise a runtime
- <classname>InvalidStateException</classname> which contains an array
of
- <literal>InvalidValue</literal>s describing each failure.</para>
-
- <programlisting><hibernate-configuration>
- ...
- <event type="pre-update">
- <listener
-
class="org.hibernate.validator.event.ValidatePreUpdateEventListener"/>
- </event>
- <event type="pre-insert">
- <listener
-
class="org.hibernate.validator.event.ValidatePreInsertEventListener"/>
- </event>
-</hibernate-configuration></programlisting>
-
- <para><note>
- <para>When using Hibernate Entity Manager, the Validation framework
- is activated out of the box. If the beans are not annotated with
- validation annotations, there is no performance cost.</para>
- </note></para>
- </sect2>
-
- <sect2>
- <title>Application-level validation</title>
-
- <para>Hibernate Validator can be applied anywhere in your application
- code.</para>
-
- <programlisting>ClassValidator personValidator = new ClassValidator(
Person.class );
-ClassValidator addressValidator = new ClassValidator( Address.class,
ResourceBundle.getBundle("messages", Locale.ENGLISH) );
-
-InvalidValue[] validationMessages =
addressValidator.getInvalidValues(address);</programlisting>
-
- <para>The first two lines prepare the Hibernate Validator for class
- checking. The first one relies upon the error messages embedded in
- Hibernate Validator (see <xref
- linkend="validator-constraints-error" />), the second one uses a
- resource bundle for these messages. It is considered a good practice to
- execute these lines once and cache the validator instances.</para>
-
- <para>The third line actually validates the
<literal>Address</literal>
- instance and returns an array of <literal>InvalidValue</literal>s.
Your
- application logic will then be able to react to the failure.</para>
-
- <para>You can also check a particular property instead of the whole
- bean. This might be useful for property per property user
- interaction</para>
-
- <programlisting>ClassValidator addressValidator = new ClassValidator(
Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) );
-
-//only get city property invalid values
-InvalidValue[] validationMessages = addressValidator.getInvalidValues(address,
"city");
-
-//only get potential city property invalid values
-InvalidValue[] validationMessages =
addressValidator.getPotentialInvalidValues("city",
"Paris")</programlisting>
- </sect2>
-
- <sect2>
- <title>Validation informations</title>
-
- <para>As a validation information carrier, hibernate provide an array of
- <classname>InvalidValue</classname>. Each
- <literal>InvalidValue</literal> has a buch of methods describing the
- individual issues.</para>
-
- <para><methodname>getBeanClass()</methodname> retrieves the
failing bean
- type</para>
-
- <para><methodname>getBean()</methodname>retrieves the failing
instance
- (if any ie not when using
- <methodname>getPotentianInvalidValues()</methodname>)</para>
-
- <para><methodname>getValue()</methodname> retrieves the failing
- value</para>
-
- <para><methodname>getMessage()</methodname> retrieves the proper
- internationalized error message</para>
-
- <para><methodname>getRootBean()</methodname> retrieves the root
bean
- instance generating the issue (useful in conjunction with
- <literal>@Valid</literal>), is null if getPotentianInvalidValues() is
- used.</para>
-
- <para><literal>getPropertyPath()</literal> retrieves the dotted
path of
- the failing property starting from the root bean</para>
- </sect2>
- </sect1>
-</chapter>
\ No newline at end of file