[hibernate-commits] Hibernate SVN: r14142 - core/trunk/documentation/manual/fr-FR/src/main/docbook/content.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Fri Oct 26 03:36:12 EDT 2007
Author: xhuang at jboss.com
Date: 2007-10-26 03:36:12 -0400 (Fri, 26 Oct 2007)
New Revision: 14142
Modified:
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/architecture.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/association_mapping.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/basic_mapping.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/configuration.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/events.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/performance.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/query_hql.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/query_sql.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/session_api.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/toolset_guide.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/transactions.xml
core/trunk/documentation/manual/fr-FR/src/main/docbook/content/tutorial.xml
Log:
Match to latest English XML
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/architecture.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/architecture.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/architecture.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -323,6 +323,14 @@
courantes sont associées au thread d'exécution. Voir les javadocs pour les détails.
</para>
</listitem>
+ <listitem>
+ <para>
+ <literal>org.hibernate.context.ManagedSessionContext</literal> - current
+ sessions are tracked by thread of execution. However, you are responsible to
+ bind and unbind a <literal>Session</literal> instance with static methods
+ on this class, it does never open, flush, or close a <literal>Session</literal>.
+ </para>
+ </listitem>
</itemizedlist>
<para>
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/association_mapping.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/association_mapping.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/association_mapping.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -365,7 +365,14 @@
<one-to-many class="Person"/>
</list>
</class>]]></programlisting>
-
+<para>
+ It is important that you define <literal>not-null="true"</literal> on the
+ <literal><key></literal> element of the collection mapping if the
+ underlying foreign key column is <literal>NOT NULL</literal>. Don't only
+ declare <literal>not-null="true"</literal> on a possible nested
+ <literal><column></literal> element, but on the <literal><key></literal>
+ element.
+ </para>
</sect2>
<sect2 id="assoc-bidirectional-121">
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/basic_mapping.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/basic_mapping.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/basic_mapping.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -98,8 +98,61 @@
des recherches de la DTD sur Internet, vérifiez votre déclaration de DTD par rapport
au contenu de votre classpath.
</para>
- </sect2>
- <sect2 id="mapping-declaration-mapping" revision="3">
+ <sect3 id="mapping-declaration-entity-resolution">
+ <title>EntityResolver</title>
+ <para>
+ As mentioned previously, Hibernate will first attempt to resolve DTDs in its classpath. The
+ manner in which it does this is by registering a custom <literal>org.xml.sax.EntityResolver</literal>
+ implementation with the SAXReader it uses to read in the xml files. This custom
+ <literal>EntityResolver</literal> recognizes two different systemId namespaces.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ a <literal>hibernate namespace</literal> is recognized whenever the
+ resolver encounteres a systemId starting with
+ <literal>http://hibernate.sourceforge.net/</literal>; the resolver
+ attempts to resolve these entities via the classlaoder which loaded
+ the Hibernate classes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a <literal>user namespace</literal> is recognized whenever the
+ resolver encounteres a systemId using a <literal>classpath://</literal>
+ URL protocol; the resolver will attempt to resolve these entities
+ via (1) the current thread context classloader and (2) the
+ classloader which loaded the Hibernate classes.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ An example of utilizing user namespacing:
+ </para>
+ <programlisting><![CDATA[<?xml version="1.0"?>
+ <!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [
+ <!ENTITY types SYSTEM "classpath://your/domain/types.xml">
+ ]>
+
+ <hibernate-mapping package="your.domain">
+ <class name="MyEntity">
+ <id name="id" type="my-custom-id-type">
+ ...
+ </id>
+ <class>
+ &types;
+ </hibernate-mapping>]]></programlisting>
+ <para>
+ Where <literal>types.xml</literal> is a resource in the <literal>your.domain</literal>
+ package and contains a custom <link linkend="mapping-types-custom">typedef</link>.
+ </para>
+ </sect3>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-mapping" revision="3">
<title>hibernate-mapping</title>
<para>
Cet élément a plusieurs attributs optionnels. Les attributs <literal>schema</literal> et <literal>catalog</literal>
@@ -357,19 +410,14 @@
pour plus d'informations.
</para>
</callout>
+
<callout arearefs="class18">
<para>
- <literal>catalog</literal> (optionnel) : The name of a database catalog used for this
- class and its table.
- </para>
- </callout>
- <callout arearefs="class19">
- <para>
<literal>check</literal> (optionnel) : expression SQL utilisée pour générer une contrainte
de vérification multi-lignes pour la génération automatique de schéma.
</para>
</callout>
- <callout arearefs="class20">
+ <callout arearefs="class19">
<para>
<literal>rowid</literal> (optionnel) : Hibernate peut utiliser des ROWID sur les bases de
données qui utilisent ce mécanisme. Par exemple avec Oracle, Hibernate peut utiliser la colonne additionnelle
@@ -377,14 +425,14 @@
la localisation physique d'un tuple enregistré.
</para>
</callout>
- <callout arearefs="class21">
+ <callout arearefs="class20">
<para>
<literal>subselect</literal> (optionnel) : Permet de mapper une entité immuable en lecture-seule
sur un sous-select de base de données. Utile pour avoir une vue au lieu d'une table en base, mais à éviter. Voir plus bas
pour plus d'information.
</para>
</callout>
- <callout arearefs="class22">
+ <callout arearefs="class21">
<para>
<literal>abstract</literal> (optionnel) : Utilisé pour marquer des superclasses abstraites dans
des hiérarchies de <literal><union-subclass></literal>.
@@ -733,6 +781,19 @@
avec une association <literal><one-to-one></literal> sur la clef primaire.
</para>
</listitem>
+ </varlistentry> <varlistentry>
+ <term><literal>sequence-identity</literal></term>
+ <listitem>
+ <para>
+ a specialized sequence generation strategy which utilizes a
+ database sequence for the actual value generation, but combines
+ this with JDBC3 getGeneratedKeys to actually return the generated
+ identifier value as part of the insert statement execution. This
+ strategy is only known to be supported on Oracle 10g drivers
+ targetted for JDK 1.4. Note comments on these insert statements
+ are disabled due to a bug in the Oracle drivers.
+ </para>
+ </listitem>
</varlistentry>
</variablelist>
</para>
@@ -829,7 +890,177 @@
</para>
</sect3>
</sect2>
- <sect2 id="mapping-declaration-compositeid" revision="3">
+
+
+ <sect2 id="mapping-declaration-id-enhanced">
+ <title>Enhanced identifier generators</title>
+
+ <para>
+ Starting with release 3.2.3, there are 2 new generators which represent a re-thinking of 2 different
+ aspects of identifier generation. The first aspect is database portability; the second is optimization
+ (not having to query the database for every request for a new identifier value). These two new
+ generators are intended to take the place of some of the named generators described above (starting
+ in 3.3.x); however, they are included in the current releases and can be referenced by FQN.
+ </para>
+
+ <para>
+ The first of these new generators is <literal>org.hibernate.id.enhanced.SequenceStyleGenerator</literal>
+ which is intended firstly as a replacement for the <literal>sequence</literal> generator and secondly as
+ a better portability generator than <literal>native</literal> (because <literal>native</literal>
+ (generally) chooses between <literal>identity</literal> and <literal>sequence</literal> which have
+ largely different semantics which can cause subtle isssues in applications eyeing portability).
+ <literal>org.hibernate.id.enhanced.SequenceStyleGenerator</literal> however achieves portability in
+ a different manner. It chooses between using a table or a sequence in the database to store its
+ incrementing values depending on the capabilities of the dialect being used. The difference between this
+ and <literal>native</literal> is that table-based and sequence-based storage have the same exact
+ semantic (in fact sequences are exactly what Hibernate tries to emmulate with its table-based
+ generators). This generator has a number of configuration parameters:
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>sequence_name</literal> (optional, defaults to <literal>hibernate_sequence</literal>):
+ The name of the sequence (or table) to be used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>initial_value</literal> (optional, defaults to <literal>1</literal>): The initial
+ value to be retrieved from the sequence/table. In sequence creation terms, this is analogous
+ to the clause typical named "STARTS WITH".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>increment_size</literal> (optional, defaults to <literal>1</literal>): The value by
+ which subsequent calls to the sequence/table should differ. In sequence creation terms, this
+ is analogous to the clause typical named "INCREMENT BY".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>force_table_use</literal> (optional, defaults to <literal>false</literal>): Should
+ we force the use of a table as the backing structure even though the dialect might support
+ sequence?
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>value_column</literal> (optional, defaults to <literal>next_val</literal>): Only
+ relevant for table structures! The name of the column on the table which is used to
+ hold the value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>optimizer</literal> (optional, defaults to <literal>none</literal>):
+ See <xref linkend="mapping-declaration-id-enhanced-optimizers"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ The second of these new generators is <literal>org.hibernate.id.enhanced.TableGenerator</literal> which
+ is intended firstly as a replacement for the <literal>table</literal> generator (although it actually
+ functions much more like <literal>org.hibernate.id.MultipleHiLoPerTableGenerator</literal>) and secondly
+ as a re-implementation of <literal>org.hibernate.id.MultipleHiLoPerTableGenerator</literal> utilizing the
+ notion of pluggable optimiziers. Essentially this generator defines a table capable of holding
+ a number of different increment values simultaneously by using multiple distinctly keyed rows. This
+ generator has a number of configuration parameters:
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>table_name</literal> (optional, defaults to <literal>hibernate_sequences</literal>):
+ The name of the table to be used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>value_column_name</literal> (optional, defaults to <literal>next_val</literal>):
+ The name of the column on the table which is used to hold the value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>segment_column_name</literal> (optional, defaults to <literal>sequence_name</literal>):
+ The name of the column on the table which is used to hold the "segement key". This is the
+ value which distinctly identifies which increment value to use.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>segment_value</literal> (optional, defaults to <literal>default</literal>):
+ The "segment key" value for the segment from which we want to pull increment values for
+ this generator.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>segment_value_length</literal> (optional, defaults to <literal>255</literal>):
+ Used for schema generation; the column size to create this segment key column.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>initial_value</literal> (optional, defaults to <literal>1</literal>):
+ The initial value to be retrieved from the table.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>increment_size</literal> (optional, defaults to <literal>1</literal>):
+ The value by which subsequent calls to the table should differ.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>optimizer</literal> (optional, defaults to <literal></literal>):
+ See <xref linkend="mapping-declaration-id-enhanced-optimizers"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+
+ <sect2 id="mapping-declaration-id-enhanced-optimizers">
+ <title>Identifier generator optimization</title>
+ <para>
+ For identifier generators which store values in the database, it is inefficient for them to hit the
+ database on each and every call to generate a new identifier value. Instead, you'd ideally want to
+ group a bunch of them in memory and only hit the database when you have exhausted your in-memory
+ value group. This is the role of the pluggable optimizers. Currently only the two enhanced generators
+ (<xref linkend="mapping-declaration-id-enhanced"/> support this notion.
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>none</literal> (generally this is the default if no optimizer was specified): This
+ says to not perform any optimizations, and hit the database each and every request.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>hilo</literal>: applies a hi/lo algorithm around the database retrieved values. The
+ values from the database for this optimizer are expected to be sequential. The values
+ retrieved from the database structure for this optimizer indicates the "group number"; the
+ <literal>increment_size</literal> is multiplied by that value in memory to define a group
+ "hi value".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>pooled</literal>: like was discussed for <literal>hilo</literal>, this optimizers
+ attempts to minimize the number of hits to the database. Here, however, we simply store
+ the starting value for the "next group" into the database structure rather than a sequential
+ value in combination with an in-memory grouping algorithm. <literal>increment_size</literal>
+ here refers to the values coming from the database.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+
+
+
+ <sect2 id="mapping-declaration-compositeid" revision="3">
<title>composite-id</title>
<programlisting><![CDATA[<composite-id
name="propertyName"
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/configuration.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/configuration.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/configuration.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -713,21 +713,28 @@
<emphasis role="strong">ex.</emphasis>
<literal>on_close</literal> (default) | <literal>after_transaction</literal> |
<literal>after_statement</literal> | <literal>auto</literal>
+ </para> <para>
+ Note that this setting only affects <literal>Session</literal>s returned from
+ <literal>SessionFactory.openSession</literal>. For <literal>Session</literal>s
+ obtained through <literal>SessionFactory.getCurrentSession</literal>, the
+ <literal>CurrentSessionContext</literal> implementation configured for use
+ controls the connection release mode for those <literal>Session</literal>s.
+ See <xref linkend="architecture-current-session"/>
</para>
</entry>
</row>
<row>
<entry>
- <literal>hibernate.connection.<emphasis><propertyName></emphasis></literal>
+ <literal>hibernate.connection.</literal><emphasis><propertyName></emphasis>
</entry>
<entry>
- Passe la propriété JDBC<literal>propertyName</literal>
+ Passe la propriété JDBC <emphasis><propertyName></emphasis>
à <literal>DriverManager.getConnection()</literal>.
</entry>
</row>
<row>
<entry>
- <literal>hibernate.jndi.<emphasis><propertyName></emphasis></literal>
+ <literal>hibernate.jndi.</literal><emphasis><propertyName></emphasis>
</entry>
<entry>
Passe la propriété <literal>propertyName</literal> à l'<literal>InitialContextFactory</literal>
@@ -1415,8 +1422,14 @@
<programlisting><![CDATA[SessionFactory sf = new Configuration().configure().buildSessionFactory();]]></programlisting>
+ <para>
+ You can pick a different XML configuration file using
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sf = new Configuration()
+ .configure("catdb.cfg.xml")
+ .buildSessionFactory();]]></programlisting>
-
</sect1>
<sect1 id="configuration-j2ee" revision="1">
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/events.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/events.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/events.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -116,15 +116,26 @@
}]]></programlisting>
- <para>
- L'intercepteur doit être spécifié quand une session est créée.
+ <para>
+ Interceptors come in two flavors: <literal>Session</literal>-scoped and
+ <literal>SessionFactory</literal>-scoped.
+ </para>
+
+ <para>
+ A <literal>Session</literal>-scoped interceptor is specified
+ when a session is opened using one of the overloaded SessionFactory.openSession()
+ methods accepting an <literal>Interceptor</literal>.
</para>
<programlisting><![CDATA[Session session = sf.openSession( new AuditInterceptor() );]]></programlisting>
- <para>
- Vous pouvez aussi mettre un intercepteur au niveau global, en utilisant l'objet <literal>Configuration</literal>.
- Dans ce cas, l'intercepteur doit être "threadsafe".
+ <para>
+ A <literal>SessionFactory</literal>-scoped interceptor is registered with the <literal>Configuration</literal>
+ object prior to building the <literal>SessionFactory</literal>. In this case, the supplied interceptor
+ will be applied to all sessions opened from that <literal>SessionFactory</literal>; this is true unless
+ a session is opened explicitly specifying the interceptor to use. <literal>SessionFactory</literal>-scoped
+ interceptors must be thread safe, taking care to not store session-specific state since multiple
+ sessions will use this interceptor (potentially) concurrently.
</para>
<programlisting><![CDATA[new Configuration().setInterceptor( new AuditInterceptor() );]]></programlisting>
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/performance.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/performance.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/performance.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -719,7 +719,7 @@
<entry>OSCache</entry>
<entry><literal>org.hibernate.cache.OSCacheProvider</literal></entry>
<entry>mémoire, disque</entry>
- <entry>oui (invalidation de cluster)</entry>
+ <entry></entry>
<entry>oui</entry>
</row>
<row>
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/query_hql.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/query_hql.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/query_hql.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -214,6 +214,43 @@
<programlisting><![CDATA[from Cat as cat where cat.mate.name like '%s%']]></programlisting>
</sect1>
+ <sect1 id="queryhql-identifier-property">
+ <title>Refering to identifier property</title>
+
+ <para>
+ There are, generally speaking, 2 ways to refer to an entity's identifier property:
+ </para>
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ The special property (lowercase) <literal>id</literal> may be used to reference the identifier
+ property of an entity <emphasis>provided that entity does not define a non-identifier property
+ named id</emphasis>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the entity defines a named identifier property, you may use that property name.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ References to composite identifier properties follow the same naming rules. If the
+ entity has a non-identifier property named id, the composite identifier property can only
+ be referenced by its defined named; otherwise, the special <literal>id</literal> property
+ can be used to rerference the identifier property.
+ </para>
+
+ <para>
+ Note: this has changed significantly starting in version 3.2.2. In previous versions,
+ <literal>id</literal> <emphasis>always</emphasis> referred to the identifier property no
+ matter what its actual name. A ramification of that decision was that non-identifier
+ properties named <literal>id</literal> could never be referenced in Hibernate queries.
+ </para>
+ </sect1>
+
+
<sect1 id="queryhql-select">
<title>La clause select</title>
@@ -904,34 +941,10 @@
Notez que les sous-requêtes HQL peuvent arriver seulememnt dans les clauses select ou where.
</para>
- <para>
- Pour des sous-requêtes avec plus d'une expression dans le select, vous pouvez utiliser un constructeur de tuples :
+ <para>
+ Note that subqueries can also utilize <literal>row value constructor</literal> syntax. See
+ <xref linkend="queryhql-tuple"/> for more details.
</para>
-
- <programlisting><![CDATA[from Cat as cat
-where not ( cat.name, cat.color ) in (
- select cat.name, cat.color from DomesticCat cat
-)]]></programlisting>
-
- <para>
- Notez que sur certaines bases de données (mais par Oracle ou HSQL), vous pouvez utiliser des constructeurs de tuples
- dans d'autres contextes, par exemple lors du requêtage de composants ou de types utilisateur composites :
- </para>
-
- <programlisting><![CDATA[from Person where name = ('Gavin', 'A', 'King')]]></programlisting>
-
- <para>
- Ce qui est équivalent à la forme plus verbeuse suivante :
- </para>
-
- <programlisting><![CDATA[from Person where name.first = 'Gavin' and name.initial = 'A' and name.last = 'King')]]></programlisting>
-
- <para>
- Il y a deux bonnes raisons que vous ne puissiez ne pas vouloir faire cette sorte de choses : d'abord, ce n'est
- pas complètement portable entre les plateformes de base de données ; deuxièmement, la requête est maintenant
- dépendante de l'ordre des propriétés dans le document de mapping.
- </para>
-
</sect1>
<sect1 id="queryhql-examples">
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/query_sql.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/query_sql.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/query_sql.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -23,226 +23,379 @@
Dans des cas extrêmement simples, nous pouvons utiliser la forme suivante :
</para>
- <programlisting>List cats = sess.createSQLQuery("select * from cats")
- .addEntity(Cat.class)
- .list();</programlisting>
+
+ <sect2>
+ <title>Scalar queries</title>
+
+ <para>The most basic SQL query is to get a list of scalars
+ (values).</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS").list();
+ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
+ ]]></programlisting>
+
+ <para>These will both return a List of Object arrays (Object[]) with
+ scalar values for each column in the CATS table. Hibernate will use
+ ResultSetMetadata to deduce the actual order and types of the returned
+ scalar values.</para>
+
+ <para>To avoid the overhead of using
+ <literal>ResultSetMetadata</literal> or simply to be more explicit in
+ what is returned one can use <literal>addScalar()</literal>.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS")
+ .addScalar("ID", Hibernate.LONG)
+ .addScalar("NAME", Hibernate.STRING)
+ .addScalar("BIRTHDATE", Hibernate.DATE)
+ ]]></programlisting>
+
+ <para>This query specified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the SQL query string</para>
+ </listitem>
+
+ <listitem>
+ <para>the columns and types to return</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>This will still return Object arrays, but now it will not use
+ <literal>ResultSetMetdata</literal> but will instead explicitly get the
+ ID, NAME and BIRTHDATE column as respectively a Long, String and a Short
+ from the underlying resultset. This also means that only these three
+ columns will be returned, even though the query is using
+ <literal>*</literal> and could return more than the three listed
+ columns.</para>
+
+ <para>It is possible to leave out the type information for all or some
+ of the scalars.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS")
+ .addScalar("ID", Hibernate.LONG)
+ .addScalar("NAME")
+ .addScalar("BIRTHDATE")
+ ]]></programlisting>
+
+ <para>This is essentially the same query as before, but now
+ <literal>ResultSetMetaData</literal> is used to decide the type of NAME
+ and BIRTHDATE where as the type of ID is explicitly specified.</para>
+
+ <para>How the java.sql.Types returned from ResultSetMetaData is mapped
+ to Hibernate types is controlled by the Dialect. If a specific type is
+ not mapped or does not result in the expected type it is possible to
+ customize it via calls to <literal>registerHibernateType</literal> in
+ the Dialect.</para>
+ </sect2>
+
+ <sect2>
+ <title>Entity queries</title>
+
+ <para>The above queries were all about returning scalar values,
+ basically returning the "raw" values from the resultset. The following
+ shows how to get entity objects from a native sql query via
+ <literal>addEntity()</literal>.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);
+ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class);
+ ]]></programlisting>
+
+ <para>This query specified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the SQL query string</para>
+ </listitem>
+
+ <listitem>
+ <para>the entity returned by the query</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Assuming that Cat is mapped as a class with the columns ID, NAME
+ and BIRTHDATE the above queries will both return a List where each
+ element is a Cat entity.</para>
+
+ <para>If the entity is mapped with a <literal>many-to-one</literal> to
+ another entity it is required to also return this when performing the
+ native query, otherwise a database specific "column not found" error
+ will occur. The additional columns will automatically be returned when
+ using the * notation, but we prefer to be explicit as in the following
+ example for a <literal>many-to-one</literal> to a
+ <literal>Dog</literal>:</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, DOG_ID FROM CATS").addEntity(Cat.class);
+ ]]></programlisting>
+
+ <para>This will allow cat.getDog() to function properly.</para>
+ </sect2>
+
+ <sect2>
+ <title>Handling associations and collections</title>
+
+ <para>It is possible to eagerly join in the <literal>Dog</literal> to
+ avoid the possible extra roundtrip for initializing the proxy. This is
+ done via the <literal>addJoin()</literal> method, which allows you to
+ join in an association or collection.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT c.ID, NAME, BIRTHDATE, DOG_ID, D_ID, D_NAME FROM CATS c, DOGS d WHERE c.DOG_ID = d.D_ID")
+ .addEntity("cat", Cat.class)
+ .addJoin("cat.dog");
+ ]]></programlisting>
+
+ <para>In this example the returned <literal>Cat</literal>'s will have
+ their <literal>dog</literal> property fully initialized without any
+ extra roundtrip to the database. Notice that we added a alias name
+ ("cat") to be able to specify the target property path of the join. It
+ is possible to do the same eager joining for collections, e.g. if the
+ <literal>Cat</literal> had a one-to-many to <literal>Dog</literal>
+ instead.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, D_ID, D_NAME, CAT_ID FROM CATS c, DOGS d WHERE c.ID = d.CAT_ID")
+ .addEntity("cat", Cat.class)
+ .addJoin("cat.dogs");
+ ]]></programlisting>
+
+ <para>
+ At this stage we are reaching the limits of what is possible with native queries without starting to
+ enhance the sql queries to make them usable in Hibernate; the problems starts to arise when returning
+ multiple entities of the same type or when the default alias/column names are not enough.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Returning multiple entities</title>
+
+ <para>Until now the result set column names are assumed to be the same
+ as the column names specified in the mapping document. This can be
+ problematic for SQL queries which join multiple tables, since the same
+ column names may appear in more than one table.</para>
+
+ <para>Column alias injection is needed in the following query (which
+ most likely will fail):</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT c.*, m.* FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
+ .addEntity("cat", Cat.class)
+ .addEntity("mother", Cat.class)
+ ]]></programlisting>
+
+ <para>The intention for this query is to return two Cat instances per
+ row, a cat and its mother. This will fail since there is a conflict of
+ names since they are mapped to the same column names and on some
+ databases the returned column aliases will most likely be on the form
+ "c.ID", "c.NAME", etc. which are not equal to the columns specificed in
+ the mappings ("ID" and "NAME").</para>
+
+ <para>The following form is not vulnerable to column name
+ duplication:</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT {cat.*}, {mother.*} FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
+ .addEntity("cat", Cat.class)
+ .addEntity("mother", Cat.class)
+ ]]></programlisting>
+
+ <para>This query specified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the SQL query string, with placeholders for Hibernate to
+ inject column aliases</para>
+ </listitem>
+
+ <listitem>
+ <para>the entities returned by the query</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The {cat.*} and {mother.*} notation used above is a shorthand for
+ "all properties". Alternatively, you may list the columns explicity, but
+ even in this case we let Hibernate inject the SQL column aliases for
+ each property. The placeholder for a column alias is just the property
+ name qualified by the table alias. In the following example, we retrieve
+ Cats and their mothers from a different table (cat_log) to the one
+ declared in the mapping metadata. Notice that we may even use the
+ property aliases in the where clause if we like.</para>
+
+ <programlisting><![CDATA[String sql = "SELECT ID as {c.id}, NAME as {c.name}, " +
+ "BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
+ "FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";
+
+ List loggedCats = sess.createSQLQuery(sql)
+ .addEntity("cat", Cat.class)
+ .addEntity("mother", Cat.class).list()
+ ]]></programlisting>
+
+ <sect3 id="querysql-aliasreferences" revision="2">
+ <title>Alias and property references</title>
+
+ <para>For most cases the above alias injection is needed, but for
+ queries relating to more complex mappings like composite properties,
+ inheritance discriminators, collections etc. there are some specific
+ aliases to use to allow Hibernate to inject the proper aliases.</para>
+
+ <para>The following table shows the different possibilities of using
+ the alias injection. Note: the alias names in the result are examples,
+ each alias will have a unique and probably different name when
+ used.</para>
+
+ <table frame="topbot" id="aliasinjection-summary">
+ <title>Alias injection names</title>
+
+ <tgroup cols="3">
+ <colspec colwidth="1*" />
+
+ <colspec colwidth="1*" />
+
+ <colspec colwidth="2.5*" />
+
+ <thead>
+ <row>
+ <entry>Description</entry>
+
+ <entry>Syntax</entry>
+
+ <entry>Example</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>A simple property</entry>
+
+ <entry><literal>{[aliasname].[propertyname]</literal></entry>
+
+ <entry><literal>A_NAME as {item.name}</literal></entry>
+ </row>
+
+ <row>
+ <entry>A composite property</entry>
+
+ <entry><literal>{[aliasname].[componentname].[propertyname]}</literal></entry>
+
+ <entry><literal>CURRENCY as {item.amount.currency}, VALUE as
+ {item.amount.value}</literal></entry>
+ </row>
+
+ <row>
+ <entry>Discriminator of an entity</entry>
+
+ <entry><literal>{[aliasname].class}</literal></entry>
+
+ <entry><literal>DISC as {item.class}</literal></entry>
+ </row>
+
+ <row>
+ <entry>All properties of an entity</entry>
+
+ <entry><literal>{[aliasname].*}</literal></entry>
+
+ <entry><literal>{item.*}</literal></entry>
+ </row>
+
+ <row>
+ <entry>A collection key</entry>
+
+ <entry><literal>{[aliasname].key}</literal></entry>
+
+ <entry><literal>ORGID as {coll.key}</literal></entry>
+ </row>
+
+ <row>
+ <entry>The id of an collection</entry>
+
+ <entry><literal>{[aliasname].id}</literal></entry>
+
+ <entry><literal>EMPID as {coll.id}</literal></entry>
+ </row>
+
+ <row>
+ <entry>The element of an collection</entry>
+
+ <entry><literal>{[aliasname].element}</literal></entry>
+
+ <entry><literal>XID as {coll.element}</literal></entry>
+ </row>
+
+ <row>
+ <entry>roperty of the element in the collection</entry>
+
+ <entry><literal>{[aliasname].element.[propertyname]}</literal></entry>
+
+ <entry><literal>NAME as {coll.element.name}</literal></entry>
+ </row>
+
+ <row>
+ <entry>All properties of the element in the collection</entry>
+
+ <entry><literal>{[aliasname].element.*}</literal></entry>
+
+ <entry><literal>{coll.element.*}</literal></entry>
+ </row>
+
+ <row>
+ <entry>All properties of the the collection</entry>
+
+ <entry><literal>{[aliasname].*}</literal></entry>
+
+ <entry><literal>{coll.*}</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Returning non-managed entities</title>
+
+ <para>It is possible to apply a ResultTransformer to native sql queries. Allowing it to e.g. return non-managed entities.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT NAME, BIRTHDATE FROM CATS")
+ .setResultTransformer(Transformers.aliasToBean(CatDTO.class))]]></programlisting>
+
+ <para>This query specified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the SQL query string</para>
+ </listitem>
+
+ <listitem>
+ <para>a result transformer</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The above query will return a list of <literal>CatDTO</literal> which has been instantiated and injected the values of NAME and BIRTHNAME into its corresponding
+ properties or fields.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Handling inheritance</title>
+
+ <para>Native sql queries which query for entities that is mapped as part
+ of an inheritance must include all properties for the baseclass and all
+ it subclasses.</para>
+ </sect2>
+
+ <sect2>
+ <title>Parameters</title>
+
+ <para>Native sql queries support positional as well as named
+ parameters:</para>
+
+ <programlisting><![CDATA[Query query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like ?").addEntity(Cat.class);
+ List pusList = query.setString(0, "Pus%").list();
+
+ query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like :name").addEntity(Cat.class);
+ List pusList = query.setString("name", "Pus%").list(); ]]></programlisting>
+ </sect2>
+
+
+</sect1>
- <para>Cette requête a spécifié :</para>
-
- <itemizedlist>
- <listitem>
- <para>la requête SQL</para>
- </listitem>
-
- <listitem>
- <para>l'entité retournée par la requête</para>
- </listitem>
- </itemizedlist>
-
- <para>
- Ici, les noms de colonne des résultats sont supposés être les mêmes que les noms de colonne spécifiés dans le
- document de mapping. Cela peut être problématique pour des requêtes SQL qui joignent de multiple tables, puisque
- les mêmes noms de colonne peuvent apparaître dans plus d'une table. La forme suivante n'est pas vulnérable à la
- duplication des noms de colonne :
- </para>
-
- <programlisting>List cats = sess.createSQLQuery("select {cat.*} from cats cat")
- .addEntity("cat", Cat.class)
- .list();</programlisting>
-
- <para>Cette requête a spécifié :</para>
-
- <itemizedlist>
- <listitem>
- <para>la requête SQL, avec un paramètre fictif pour Hibernate pour injecter les alias de colonne</para>
- </listitem>
-
- <listitem>
- <para>l'entité retournée par la requête, et son alias de table SQL</para>
- </listitem>
- </itemizedlist>
-
- <para>
- La méthode <literal>addEntity()</literal> associe l'alias de la table SQL
- avec la classe de l'entité retournée, et détermine la forme de l'ensemble des résultats de la requête.
- </para>
-
- <para>
- La méthode <literal>addJoin()</literal> peut être utilisée pour charger des associations vers d'autres
- entités et collections.
- </para>
-
- <programlisting>List cats = sess.createSQLQuery(
- "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
- )
- .addEntity("cat", Cat.class)
- .addJoin("kitten", "cat.kittens")
- .list();</programlisting>
-
- <para>
- Une requête SQL native pourrait retourner une simple valeur scalaire ou une combinaison de scalaires et d'entités.
- </para>
-
- <programlisting>Double max = (Double) sess.createSQLQuery("select max(cat.weight) as maxWeight from cats cat")
- .addScalar("maxWeight", Hibernate.DOUBLE);
- .uniqueResult();</programlisting>
-
- <para>Vous pouvez alternativement décrire les informations de mapping des résultats dans vos fichiers hbm
- et les utiliser pour vos requêtes.</para>
-
- <programlisting>List cats = sess.createSQLQuery(
- "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
- )
- .setResultSetMapping("catAndKitten")
- .list();</programlisting>
- </sect1>
-
- <sect1 id="querysql-aliasreferences">
- <title>Alias et références de propriété</title>
-
- <para>
- La notation <literal>{cat.*}</literal> utilisée au-dessus est un raccourci pour "toutes les propriétés".
- Alternativement, vous pouvez lister explicitement les colonnes, mais même ce cas que nous laissons à Hibernate
- injecte des alias de colonne SQL pour chaque propriété. Le remplaçant pour un alias de colonne
- est juste le nom de la propriété qualifié par l'alias de la table.
- Dans l'exemple suivant, nous récupérons des <literal>Cat</literal>s à partir d'une table différente
- (<literal>cat_log</literal>) de celle déclarée dans les méta-données de mapping.
- Notez que nous pouvons même utiliser les alias de propriété dans la clause "where" si nous le souhaitons.
- </para>
-
- <para>
- La syntaxe <literal>{}</literal> <emphasis>n'est pas</emphasis> requise pour le requêtes nommées. Voir
- <xref linkend="querysql-namedqueries" />.
- </para>
-
- <programlisting>String sql = "select cat.originalId as {cat.id}, " +
- "cat.mateid as {cat.mate}, cat.sex as {cat.sex}, " +
- "cat.weight*10 as {cat.weight}, cat.name as {cat.name} " +
- "from cat_log cat where {cat.mate} = :catId"
-
-List loggedCats = sess.createSQLQuery(sql)
- .addEntity("cat", Cat.class)
- .setLong("catId", catId)
- .list();</programlisting>
-
- <para>
- <emphasis>À noter :</emphasis> si vous listez chaque propriété explicitement, vous devez inclure
- toutes les propriétés de la classe <emphasis>et ses sous-classes</emphasis> !
- </para>
-
- <para>
- La table suivante montre les différentes possibilités d'utilisation de l'injection d'alias. À noter : les noms
- des alias dans le résultat sont des exemples, chaque alias aura un nom unique et probablement différent lors de l'utilisation.
- </para>
-
- <table frame="topbot" id="aliasinjection-summary">
- <title>Noms d'injection d'alias</title>
-
- <tgroup cols="4">
- <colspec colwidth="1*" />
-
- <colspec colwidth="1*" />
-
- <colspec colwidth="2.5*" />
-
- <thead>
- <row>
- <entry>Description</entry>
-
- <entry>Syntaxe</entry>
-
- <entry>Exemple</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>Une simple propriété</entry>
-
- <entry><literal>{[aliasname].[propertyname]}</literal></entry>
-
- <entry><literal>A_NAME as {item.name}</literal></entry>
- </row>
-
- <row>
- <entry>Une propriété composée</entry>
-
- <entry><literal>{[aliasname].[componentname].[propertyname]}</literal></entry>
-
- <entry><literal>CURRENCY as {item.amount.currency}, VALUE as
- {item.amount.value}</literal></entry>
- </row>
-
- <row>
- <entry>Discriminant d'une entité</entry>
-
- <entry><literal>{[aliasname].class}</literal></entry>
-
- <entry><literal>DISC as {item.class}</literal></entry>
- </row>
-
- <row>
- <entry>Toutes les propriétés d'une entité</entry>
-
- <entry><literal>{[aliasname].*}</literal></entry>
-
- <entry><literal>{item.*}</literal></entry>
- </row>
-
- <row>
- <entry>Une clef de collection</entry>
-
- <entry><literal>{[aliasname].key}</literal></entry>
-
- <entry><literal>ORGID as {coll.key}</literal></entry>
- </row>
-
- <row>
- <entry>L'identifiant d'une collection</entry>
-
- <entry><literal>{[aliasname].id}</literal></entry>
-
- <entry><literal>EMPID as {coll.id}</literal></entry>
- </row>
-
- <row>
- <entry>L'élément d'une collection</entry>
-
- <entry><literal>{[aliasname].element}</literal></entry>
-
- <entry><literal>XID as {coll.element}</literal></entry>
-
- <entry></entry>
- </row>
-
- <row>
- <entry>Propriété de l'élément dans la collection</entry>
-
- <entry><literal>{[aliasname].element.[propertyname]}</literal></entry>
-
- <entry><literal>NAME as {coll.element.name}</literal></entry>
- </row>
-
- <row>
- <entry>Toutes les propriétés de l'élément dans la collection</entry>
-
- <entry><literal>{[aliasname].element.*}</literal></entry>
-
- <entry><literal>{coll.element.*}</literal></entry>
- </row>
-
- <row>
- <entry>Toutes les propriétés de la collection</entry>
-
- <entry><literal>{[aliasname].*}</literal></entry>
-
- <entry><literal>{coll.*}</literal></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </sect1>
-
<sect1 id="querysql-namedqueries" revision="3">
<title>Requêtes SQL nommées</title>
@@ -252,54 +405,54 @@
cas, nous <emphasis>n'avons pas besoin</emphasis> d'appeler <literal>addEntity()</literal>.
</para>
- <programlisting><sql-query name="persons">
- <return alias="person" class="eg.Person"/>
- SELECT person.NAME AS {person.name},
- person.AGE AS {person.age},
- person.SEX AS {person.sex}
- FROM PERSON person
- WHERE person.NAME LIKE :namePattern
-</sql-query></programlisting>
+ <programlisting><![CDATA[<sql-query name="persons">
+ <return alias="person" class="eg.Person"/>
+ SELECT person.NAME AS {person.name},
+ person.AGE AS {person.age},
+ person.SEX AS {person.sex}
+ FROM PERSON person
+ WHERE person.NAME LIKE :namePattern
+ </sql-query>]]></programlisting>
+
+ <programlisting><![CDATA[List people = sess.getNamedQuery("persons")
+ .setString("namePattern", namePattern)
+ .setMaxResults(50)
+ .list();]]></programlisting>
- <programlisting>List people = sess.getNamedQuery("persons")
- .setString("namePattern", namePattern)
- .setMaxResults(50)
- .list();</programlisting>
-
<para>
Les éléments <literal><return-join></literal> et
<literal><load-collection></literal> sont respectivement utilisés pour lier
des associations et définir des requêtes qui initialisent des collections.
</para>
- <programlisting><sql-query name="personsWith">
- <return alias="person" class="eg.Person"/>
- <return-join alias="address" property="person.mailingAddress"/>
- SELECT person.NAME AS {person.name},
- person.AGE AS {person.age},
- person.SEX AS {person.sex},
- address.STREET AS {address.street},
- address.CITY AS {address.city},
- address.STATE AS {address.state},
- address.ZIP AS {address.zip}
- FROM PERSON person
- JOIN ADDRESS address
- ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
- WHERE person.NAME LIKE :namePattern
-</sql-query></programlisting>
+ <programlisting><![CDATA[<sql-query name="personsWith">
+ <return alias="person" class="eg.Person"/>
+ <return-join alias="address" property="person.mailingAddress"/>
+ SELECT person.NAME AS {person.name},
+ person.AGE AS {person.age},
+ person.SEX AS {person.sex},
+ address.STREET AS {address.street},
+ address.CITY AS {address.city},
+ address.STATE AS {address.state},
+ address.ZIP AS {address.zip}
+ FROM PERSON person
+ JOIN ADDRESS address
+ ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
+ WHERE person.NAME LIKE :namePattern
+</sql-query>]]></programlisting>
<para>
Une requête SQL nommée peut retourner une valeur scalaire. Vous devez
spécifier l'alias de colonne et le type Hibernate utilisant l'élément
<literal><return-scalar></literal> :</para>
- <programlisting><sql-query name="mySqlQuery">
- <return-scalar column="name" type="string"/>
- <return-scalar column="age" type="long"/>
- SELECT p.NAME AS name,
- p.AGE AS age,
- FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
-</sql-query></programlisting>
+<programlisting><![CDATA[<sql-query name="mySqlQuery">
+ <return-scalar column="name" type="string"/>
+ <return-scalar column="age" type="long"/>
+ SELECT p.NAME AS name,
+ p.AGE AS age,
+ FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
+</sql-query>]]></programlisting>
<para>
Vous pouvez externaliser les informations de mapping des résultats dans un
@@ -308,24 +461,32 @@
<literal>setResultSetMapping()</literal>.
</para>
- <programlisting><resultset name="personAddress">
- <return alias="person" class="eg.Person"/>
- <return-join alias="address" property="person.mailingAddress"/>
-</resultset>
+ <programlisting><![CDATA[<resultset name="personAddress">
+ <return alias="person" class="eg.Person"/>
+ <return-join alias="address" property="person.mailingAddress"/>
+ </resultset>
+
+ <sql-query name="personsWith" resultset-ref="personAddress">
+ SELECT person.NAME AS {person.name},
+ person.AGE AS {person.age},
+ person.SEX AS {person.sex},
+ address.STREET AS {address.street},
+ address.CITY AS {address.city},
+ address.STATE AS {address.state},
+ address.ZIP AS {address.zip}
+ FROM PERSON person
+ JOIN ADDRESS address
+ ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
+ WHERE person.NAME LIKE :namePattern
+</sql-query>]]></programlisting>
+<para>You can alternatively use the resultset mapping information in your
+ hbm files directly in java code.</para>
-<sql-query name="personsWith" resultset-ref="personAddress">
- SELECT person.NAME AS {person.name},
- person.AGE AS {person.age},
- person.SEX AS {person.sex},
- address.STREET AS {address.street},
- address.CITY AS {address.city},
- address.STATE AS {address.state},
- address.ZIP AS {address.zip}
- FROM PERSON person
- JOIN ADDRESS address
- ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
- WHERE person.NAME LIKE :namePattern
-</sql-query></programlisting>
+<programlisting><![CDATA[List cats = sess.createSQLQuery(
+ "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
+ )
+ .setResultSetMapping("catAndKitten")
+ .list();]]></programlisting>
<sect2 id="propertyresults">
<title>Utilisation de return-property pour spécifier explicitement les noms des colonnes/alias</title>
@@ -336,18 +497,18 @@
<literal>{}</literal> pour laisser Hibernate injecter ses propres alias.
</para>
- <programlisting><sql-query name="mySqlQuery">
- <return alias="person" class="eg.Person">
- <return-property name="name" column="myName"/>
- <return-property name="age" column="myAge"/>
- <return-property name="sex" column="mySex"/>
- </return>
- SELECT person.NAME AS myName,
- person.AGE AS myAge,
- person.SEX AS mySex,
- FROM PERSON person WHERE person.NAME LIKE :name
-</sql-query>
-</programlisting>
+ <programlisting><![CDATA[<sql-query name="mySqlQuery">
+ <return alias="person" class="eg.Person">
+ <return-property name="name" column="myName"/>
+ <return-property name="age" column="myAge"/>
+ <return-property name="sex" column="mySex"/>
+ </return>
+ SELECT person.NAME AS myName,
+ person.AGE AS myAge,
+ person.SEX AS mySex,
+ FROM PERSON person WHERE person.NAME LIKE :name
+ </sql-query>
+]]></programlisting>
<para>
<literal><return-property></literal> fonctionne aussi avec de
@@ -355,21 +516,22 @@
qui ne peut pas permettre une bonne granularité des propriétés multi-colonnes.
</para>
- <programlisting><sql-query name="organizationCurrentEmployments">
- <return alias="emp" class="Employment">
- <return-property name="salary">
- <return-column name="VALUE"/>
- <return-column name="CURRENCY"/>
- </return-property>
- <return-property name="endDate" column="myEndDate"/>
- </return>
- SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
- STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
- REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY
- FROM EMPLOYMENT
- WHERE EMPLOYER = :id AND ENDDATE IS NULL
- ORDER BY STARTDATE ASC
-</sql-query></programlisting>
+
+ <programlisting><![CDATA[<sql-query name="organizationCurrentEmployments">
+ <return alias="emp" class="Employment">
+ <return-property name="salary">
+ <return-column name="VALUE"/>
+ <return-column name="CURRENCY"/>
+ </return-property>
+ <return-property name="endDate" column="myEndDate"/>
+ </return>
+ SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
+ STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
+ REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY
+ FROM EMPLOYMENT
+ WHERE EMPLOYER = :id AND ENDDATE IS NULL
+ ORDER BY STARTDATE ASC
+</sql-query>]]></programlisting>
<para>
Notez que dans cet exemple nous avons utilisé <literal><return-property></literal>
@@ -396,36 +558,37 @@
version supérieure :
</para>
- <programlisting>CREATE OR REPLACE FUNCTION selectAllEmployments
- RETURN SYS_REFCURSOR
-AS
- st_cursor SYS_REFCURSOR;
-BEGIN
- OPEN st_cursor FOR
- SELECT EMPLOYEE, EMPLOYER,
- STARTDATE, ENDDATE,
- REGIONCODE, EID, VALUE, CURRENCY
- FROM EMPLOYMENT;
- RETURN st_cursor;
- END;</programlisting>
+ <programlisting><![CDATA[CREATE OR REPLACE FUNCTION selectAllEmployments
+ RETURN SYS_REFCURSOR
+ AS
+ st_cursor SYS_REFCURSOR;
+ BEGIN
+ OPEN st_cursor FOR
+ SELECT EMPLOYEE, EMPLOYER,
+ STARTDATE, ENDDATE,
+ REGIONCODE, EID, VALUE, CURRENCY
+ FROM EMPLOYMENT;
+ RETURN st_cursor;
+ END;]]></programlisting>
+
<para>Pour utiliser cette requête dans Hibernate vous avez besoin de la mapper via une requête nommée.</para>
- <programlisting><sql-query name="selectAllEmployees_SP" callable="true">
- <return alias="emp" class="Employment">
- <return-property name="employee" column="EMPLOYEE"/>
- <return-property name="employer" column="EMPLOYER"/>
- <return-property name="startDate" column="STARTDATE"/>
- <return-property name="endDate" column="ENDDATE"/>
- <return-property name="regionCode" column="REGIONCODE"/>
- <return-property name="id" column="EID"/>
- <return-property name="salary">
- <return-column name="VALUE"/>
- <return-column name="CURRENCY"/>
- </return-property>
- </return>
- { ? = call selectAllEmployments() }
-</sql-query></programlisting>
+ <programlisting><![CDATA[<sql-query name="selectAllEmployees_SP" callable="true">
+ <return alias="emp" class="Employment">
+ <return-property name="employee" column="EMPLOYEE"/>
+ <return-property name="employer" column="EMPLOYER"/>
+ <return-property name="startDate" column="STARTDATE"/>
+ <return-property name="endDate" column="ENDDATE"/>
+ <return-property name="regionCode" column="REGIONCODE"/>
+ <return-property name="id" column="EID"/>
+ <return-property name="salary">
+ <return-column name="VALUE"/>
+ <return-column name="CURRENCY"/>
+ </return-property>
+ </return>
+ { ? = call selectAllEmployments() }
+</sql-query>]]></programlisting>
<para>
Notez que les procédures stockées retournent, pour le moment, seulement des
@@ -447,7 +610,10 @@
<para>Les requêtes de procédures stockées ne peuvent pas être paginées avec
<literal>setFirstResult()/setMaxResults()</literal>.</para>
-
+ <para>Recommended call form is standard SQL92: <literal>{ ? = call
+ functionName(<parameters>) }</literal> or <literal>{ ? = call
+ procedureName(<parameters>}</literal>. Native call syntax is not
+ supported.</para>
<para>Pour Oracle les règles suivantes s'appliquent :</para>
<itemizedlist spacing="compact">
@@ -493,15 +659,15 @@
<literal><sql-delete></literal>, et
<literal><sql-update></literal> surchargent ces chaînes de caractères :</para>
- <programlisting><class name="Person">
- <id name="id">
- <generator class="increment"/>
- </id>
- <property name="name" not-null="true"/>
- <sql-insert>INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? )</sql-insert>
- <sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?</sql-update>
- <sql-delete>DELETE FROM PERSON WHERE ID=?</sql-delete>
-</class></programlisting>
+<programlisting><![CDATA[<class name="Person">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="name" not-null="true"/>
+ <sql-insert>INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? )</sql-insert>
+ <sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?</sql-update>
+ <sql-delete>DELETE FROM PERSON WHERE ID=?</sql-delete>
+</class>]]></programlisting>
<para>Le SQL est directement exécuté dans votre base de données, donc vous êtes libre d'utiliser
le dialecte que vous souhaitez. Cela réduira bien sûr la portabilité de votre mapping si vous
@@ -509,15 +675,16 @@
<para>Les procédures stockées sont supportées si l'attribut <literal>callable</literal> est paramétré :</para>
- <programlisting><class name="Person">
- <id name="id">
- <generator class="increment"/>
- </id>
- <property name="name" not-null="true"/>
- <sql-insert callable="true">{call createPerson (?, ?)}</sql-insert>
- <sql-delete callable="true">{? = call deletePerson (?)}</sql-delete>
- <sql-update callable="true">{? = call updatePerson (?, ?)}</sql-update>
-</class></programlisting>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="name" not-null="true"/>
+ <sql-insert callable="true">{call createPerson (?, ?)}</sql-insert>
+ <sql-delete callable="true">{? = call deletePerson (?)}</sql-delete>
+ <sql-update callable="true">{? = call updatePerson (?, ?)}</sql-update>
+</class>]]></programlisting>
<para>L'ordre des paramètres positionnels est actuellement vital, car ils doivent être dans la
même séquence qu'Hibernate les attend.</para>
@@ -536,19 +703,20 @@
Hibernate inscrit toujours la première expression comme un paramètre de sortie numérique pour les
opérations CUD :</para>
- <programlisting>CREATE OR REPLACE FUNCTION updatePerson (uid IN NUMBER, uname IN VARCHAR2)
- RETURN NUMBER IS
-BEGIN
- update PERSON
- set
- NAME = uname,
- where
- ID = uid;
-
- return SQL%ROWCOUNT;
-
-END updatePerson;</programlisting>
+<programlisting><![CDATA[CREATE OR REPLACE FUNCTION updatePerson (uid IN NUMBER, uname IN VARCHAR2)
+ RETURN NUMBER IS
+ BEGIN
+
+ update PERSON
+ set
+ NAME = uname,
+ where
+ ID = uid;
+
+ return SQL%ROWCOUNT;
+
+END updatePerson;]]></programlisting>
</sect1>
<sect1 id="querysql-load">
@@ -556,53 +724,52 @@
<para>Vous pouvez aussi déclarer vos propres requêtes SQL (ou HQL) pour le chargement d'entité :</para>
- <programlisting><sql-query name="person">
- <return alias="pers" class="Person" lock-mode="upgrade"/>
- SELECT NAME AS {pers.name}, ID AS {pers.id}
- FROM PERSON
- WHERE ID=?
- FOR UPDATE
-</sql-query></programlisting>
+
+ <programlisting><![CDATA[<sql-query name="person">
+ <return alias="pers" class="Person" lock-mode="upgrade"/>
+ SELECT NAME AS {pers.name}, ID AS {pers.id}
+ FROM PERSON
+ WHERE ID=?
+ FOR UPDATE
+</sql-query>]]></programlisting>
<para>Ceci est juste une déclaration de requête nommée, comme vu plus tôt. Vous pouvez référencer
cette requête nommée dans un mapping de classe :</para>
+<programlisting><![CDATA[<class name="Person">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="name" not-null="true"/>
+ <loader query-ref="person"/>
+</class>]]></programlisting>
- <programlisting><class name="Person">
- <id name="id">
- <generator class="increment"/>
- </id>
- <property name="name" not-null="true"/>
- <loader query-ref="person"/>
-</class></programlisting>
-
<para>Ceci fonctionne même avec des procédures stockées.</para>
<para>Vous pouvez même définir une requête pour le chargement d'une collection :</para>
+ <programlisting><![CDATA[<set name="employments" inverse="true">
+ <key/>
+ <one-to-many class="Employment"/>
+ <loader query-ref="employments"/>
+ </set>]]></programlisting>
+
+ <programlisting><![CDATA[<sql-query name="employments">
+ <load-collection alias="emp" role="Person.employments"/>
+ SELECT {emp.*}
+ FROM EMPLOYMENT emp
+ WHERE EMPLOYER = :id
+ ORDER BY STARTDATE ASC, EMPLOYEE ASC
+</sql-query>]]></programlisting>
- <programlisting><set name="employments" inverse="true">
- <key/>
- <one-to-many class="Employment"/>
- <loader query-ref="employments"/>
-</set></programlisting>
-
- <programlisting><sql-query name="employments">
- <load-collection alias="emp" role="Person.employments"/>
- SELECT {emp.*}
- FROM EMPLOYMENT emp
- WHERE EMPLOYER = :id
- ORDER BY STARTDATE ASC, EMPLOYEE ASC
-</sql-query></programlisting>
-
<para>Vous pourriez même définir un chargeur d'entité qui charge une collection par jointure :</para>
- <programlisting><sql-query name="person">
- <return alias="pers" class="Person"/>
- <return-join alias="emp" property="pers.employments"/>
- SELECT NAME AS {pers.*}, {emp.*}
- FROM PERSON pers
- LEFT OUTER JOIN EMPLOYMENT emp
- ON pers.ID = emp.PERSON_ID
- WHERE ID=?
-</sql-query></programlisting>
+ <programlisting><![CDATA[<sql-query name="person">
+ <return alias="pers" class="Person"/>
+ <return-join alias="emp" property="pers.employments"/>
+ SELECT NAME AS {pers.*}, {emp.*}
+ FROM PERSON pers
+ LEFT OUTER JOIN EMPLOYMENT emp
+ ON pers.ID = emp.PERSON_ID
+ WHERE ID=?
+</sql-query>]]></programlisting>
</sect1>
</chapter>
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/session_api.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/session_api.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/session_api.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -94,6 +94,30 @@
Vous pouvez aussi utiliser <literal>persist()</literal> à la place de<literal>save()</literal>,
avec la sémantique définie plus tôt dans le brouillon d'EJB3.
</para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>persist()</literal> makes a transient instance persistent.
+ However, it doesn't guarantee that the identifier value will be assigned to
+ the persistent instance immediately, the assignment might happen at flush time.
+ <literal>persist()</literal> also guarantees that it will not execute an
+ <literal>INSERT</literal> statement if it is called outside of transaction
+ boundaries. This is useful in long-running conversations with an extended
+ Session/persistence context.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>save()</literal> does guarantee to return an identifier. If an INSERT
+ has to be executed to get the identifier ( e.g. "identity" generator, not
+ "sequence"), this INSERT happens immediately, no matter if you are inside or
+ outside of a transaction. This is problematic in a long-running conversation
+ with an extended Session/persistence context.
+ </para>
+ </listitem>
+ </itemizedlist>
+
<para>
Alternativement, vous pouvez assigner l'identifiant en utilisant une version
@@ -307,8 +331,8 @@
while ( kittensAndMothers.hasNext() ) {
Object[] tuple = (Object[]) kittensAndMothers.next();
- Cat kitten = (Cat) tuple[0];
- Cat mother = (Cat) tuple[1];
+ Cat kitten = (Cat) tuple[0];
+ Cat mother = (Cat) tuple[1];
....
}]]></programlisting>
@@ -478,6 +502,13 @@
utilisé, vous pouvez aussi définir des requêtes SQL nativez dans les méta-données, ou
migrer des requêtes existantes vers Hibernate en les plaçant dans les fichiers de mapping.
</para>
+ <para> UNTRANSLATED!
+ Also note that a query declaration inside a <literal><hibernate-mapping></literal>
+ element requires a global unique name for the query, while a query declaration inside a
+ <literal><class></literal> element is made unique automatically by prepending the
+ fully qualified name of the class, for example
+ <literal>eg.Cat.ByNameAndMaximumWeight</literal>.
+ </para>
</sect3>
@@ -560,16 +591,16 @@
l'API Hibernate, vous devez mettre les alias SQL entre accolades :
</para>
- <programlisting><![CDATA[List cats = session.createSQLQuery("SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10")
- .addEntity("cat", Cat.class)
-.list();]]></programlisting>
-
- <programlisting><![CDATA[List cats = session.createSQLQuery(
- "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " +
- "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " +
- "FROM CAT {cat} WHERE ROWNUM<10")
- .addEntity("cat", Cat.class)
-.list()]]></programlisting>
+ <programlisting><![CDATA[List cats = session.createSQLQuery("SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10")
+ .addEntity("cat", Cat.class)
+.list();]]></programlisting>
+
+ <programlisting><![CDATA[List cats = session.createSQLQuery(
+ "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " +
+ "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " +
+ "FROM CAT {cat} WHERE ROWNUM<10")
+ .addEntity("cat", Cat.class)
+.list()]]></programlisting>
<para>
Les requêtes SQL peuvent contenir des paramètres nommés et positionnels, comme des
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/toolset_guide.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/toolset_guide.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/toolset_guide.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -219,7 +219,9 @@
<entry>
spécifie le nom d'une contrainte de clé étrangère générée pour
une association, utilisez-la avec les éléments de mapping
- <one-to-one>, <many-to-one>, <key>, et <many-to-many>
+ <literal><one-to-one></literal>,
+ <literal><many-to-one></literal>, <literal><key></literal>,
+ or <literal><many-to-many></literal>
Notez que les extrêmités <literal>inverse="true"</literal>
se seront pas prises en compte par <literal>SchemaExport</literal>.
</entry>
@@ -451,8 +453,8 @@
</para>
<para>
- <literal>java -cp </literal><emphasis>classpath_hibernate</emphasis>
- <literal>net.sf.hibernate.tool.hbm2ddl.SchemaUpdate</literal> <emphasis>options fichiers_de_mapping</emphasis>
+ <literal>java -cp </literal><emphasis>hibernate_classpaths</emphasis>
+ <literal>org.hibernate.tool.hbm2ddl.SchemaUpdate</literal> <emphasis>options mapping_files</emphasis>
</para>
<table frame="topbot">
@@ -482,6 +484,9 @@
<row>
<entry><literal>--properties=hibernate.properties</literal></entry>
<entry>lire les propriétés de la base de données à partir d'un fichier</entry>
+ </row> <row>
+ <entry><literal>--config=hibernate.cfg.xml</literal></entry>
+ <entry>specify a <literal>.cfg.xml</literal> file</entry>
</row>
</tbody>
</tgroup>
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/transactions.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/transactions.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/transactions.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -800,7 +800,12 @@
pour conserver la <literal>Session</literal> et évitez de la sérialiser et de la transférer à la couche de présentation (i.e. Il est préférable de ne pas
la conserver dans la session <literal>HttpSession</literal> .)
</para>
-
+ <para>
+ The extended session pattern, or <emphasis>session-per-conversation</emphasis>, is
+ more difficult to implement with automatic current session context management.
+ You need to supply your own implementation of the <literal>CurrentSessionContext</literal>
+ for this, see the Hibernate Wiki for examples.
+ </para>
</sect2>
<sect2 id="transactions-optimistic-detached">
Modified: core/trunk/documentation/manual/fr-FR/src/main/docbook/content/tutorial.xml
===================================================================
--- core/trunk/documentation/manual/fr-FR/src/main/docbook/content/tutorial.xml 2007-10-26 07:34:37 UTC (rev 14141)
+++ core/trunk/documentation/manual/fr-FR/src/main/docbook/content/tutorial.xml 2007-10-26 07:36:12 UTC (rev 14142)
@@ -681,7 +681,9 @@
La méthode <literal>getCurrentSession()</literal> renvoie toujours l'unité de travail courante.
Souvenez vous que nous avons basculé notre option de configuration au mécanisme basé sur le "thread"
dans <literal>hibernate.cfg.xml</literal>. Par conséquent, le scope de l'unité de travail
- courante est le thread java courant d'exécution. Ceci n'est pas totalement vrai. Une
+ courante est le thread java courant d'exécution. Ceci n'est pas totalement vrai. </para>
+
+ <para>Une
<literal>Session</literal> commence lorsqu'elle est vraiment utilisée la première fois,
Lorsque nous appelons pour la première fois <literal>getCurrentSession()</literal>.
Ensuite, elle est liée, par Hibernate, au thread courant. Lorsque la transaction s'achève
@@ -691,7 +693,17 @@
Ce modèle de programmation "<emphasis>thread-bound</emphasis>" est le moyen le plus
populaire d'utiliser Hibernate.
</para>
-
+ <para> UNTRANSLATED
+ !
+ Related to the unit of work scope, should the Hibernate <literal>Session</literal> be used to
+ execute one or several database operations? The above example uses one <literal>Session</literal>
+ for one operation. This is pure coincidence, the example is just not complex enough to show any
+ other approach. The scope of a Hibernate <literal>Session</literal> is flexible but you should
+ never design your application to use a new Hibernate <literal>Session</literal> for
+ <emphasis>every</emphasis> database operation. So even if you see it a few more times in
+ the following (very trivial) examples, consider <emphasis>session-per-operation</emphasis>
+ an anti-pattern. A real (web) application is shown later in this tutorial.
+ </para>
<para>
Lisez <xref linkend="transactions"/> pour plus d'informations sur la gestion des transactions et leur démarcations.
Nous n'avons pas géré les erreurs et rollback sur l'exemple précédent.
@@ -801,7 +813,13 @@
les événements que vous avez stockés jusque là. Vous pouvez bien sûr aussi appeler l'action
<literal>store</literal> plusieurs fois.
</para>
-
+ <para> UNTRANSLATED!
+ Note: Most new Hibernate users fail at this point and we see questions about
+ <emphasis>Table not found</emphasis> error messages regularly. However, if you follow the
+ steps outlined above you will not have this problem, as hbm2ddl creates the database
+ schema on the first run, and subsequent application restarts will use this schema. If
+ you change the mapping and/or database schema, you have to re-enable hbm2ddl once again.
+ </para>
</sect2>
</sect1>
@@ -1285,7 +1303,12 @@
doesn't scale anymore with our growing application.
</para>
-->
+
</sect2>
+ <para>
+ Let's turn this into a small web application.
+ </para>
+
</sect1>
<sect1 id="tutorial-webapp">
@@ -1305,29 +1328,20 @@
Créons une nouvelle classe dans notre répertoire source, dans le package <literal>events</literal>:
</para>
- <programlisting><![CDATA[package events;
-
-// Imports
-
-public class EventManagerServlet extends HttpServlet {
-
- private final SimpleDateFormat dateFormatter =
- new SimpleDateFormat("dd.MM.yyyy");
-
- // Servlet code
-}]]></programlisting>
-
- <para>
- Le <literal>dateFormatter</literal> est un outil que nous utiliserons plus tard pour convertir les objets
- <literal>Date</literal> depuis et vers des chaines de caractères. Il est propice de n'avoir qu'un
- formatter comme membre de la servlet.
+ <programlisting><![CDATA[package events;
+
+ // Imports
+
+ public class EventManagerServlet extends HttpServlet {
+
+ // Servlet code
+ }]]></programlisting>
+
+ <para>
+ The servlet handles HTTP <literal>GET</literal> requests only, hence, the method
+ we implement is <literal>doGet()</literal>:
</para>
- <para>
- La servlet n'accepte que les requêtes HTTP <literal>GET</literal>, la méthode à implémenter est donc
- <literal>doGet()</literal>:
- </para>
-
<programlisting><![CDATA[protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
@@ -1359,7 +1373,12 @@
tous les accès à la base de données interviennent au sein de la transactiton, peu importe que les données
soient lues ou écrites (nous n'utilisons pas le mode auto-commit dans les applications).
</para>
-
+ <para> UNTRANSLATED
+ Do <emphasis>not</emphasis> use a new Hibernate <literal>Session</literal> for
+ every database operation. Use one Hibernate <literal>Session</literal> that is
+ scoped to the whole request. Use <literal>getCurrentSession()</literal>, so that
+ it is automatically bound to the current Java thread.
+ </para>
<para>
Ensuite, les actions possibles de la requêtes sont exécutées et la réponse HTML
est rendue. Nous en parlerons plus tard.
More information about the hibernate-commits
mailing list