Match to latest English XML
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@14142 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
f134d4ab5c
commit
1a1fc99092
|
@ -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>
|
||||
|
|
|
@ -365,7 +365,14 @@ create table Address ( addressId bigint not null primary key )
|
|||
<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">
|
||||
|
|
|
@ -98,7 +98,60 @@
|
|||
des recherches de la DTD sur Internet, vérifiez votre déclaration de DTD par rapport
|
||||
au contenu de votre classpath.
|
||||
</para>
|
||||
<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>
|
||||
|
@ -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,6 +890,176 @@
|
|||
</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
|
||||
|
||||
<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
|
||||
|
|
|
@ -713,21 +713,28 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
|
|||
<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,7 +1422,13 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
|
|||
|
||||
<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>
|
||||
|
||||
|
|
|
@ -117,14 +117,25 @@ public class AuditInterceptor extends EmptyInterceptor {
|
|||
}]]></programlisting>
|
||||
|
||||
<para>
|
||||
L'intercepteur doit être spécifié quand une session est créée.
|
||||
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".
|
||||
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>
|
||||
|
|
|
@ -719,7 +719,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
|
|||
<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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
@ -905,33 +942,9 @@ from Cat as cat]]></programlisting>
|
|||
</para>
|
||||
|
||||
<para>
|
||||
Pour des sous-requêtes avec plus d'une expression dans le select, vous pouvez utiliser un constructeur de tuples :
|
||||
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">
|
||||
|
|
|
@ -23,122 +23,226 @@
|
|||
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>
|
||||
|
||||
<para>Cette requête a spécifié :</para>
|
||||
<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>la requête SQL</para>
|
||||
<para>the SQL query string</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>l'entité retournée par la requête</para>
|
||||
<para>the columns and types to return</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>
|
||||
<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>
|
||||
|
||||
<programlisting>List cats = sess.createSQLQuery("select {cat.*} from cats cat")
|
||||
.addEntity("cat", Cat.class)
|
||||
.list();</programlisting>
|
||||
<para>It is possible to leave out the type information for all or some
|
||||
of the scalars.</para>
|
||||
|
||||
<para>Cette requête a spécifié :</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>la requête SQL, avec un paramètre fictif pour Hibernate pour injecter les alias de colonne</para>
|
||||
<para>the SQL query string</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>l'entité retournée par la requête, et son alias de table SQL</para>
|
||||
<para>the entity returned by the query</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>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>
|
||||
La méthode <literal>addJoin()</literal> peut être utilisée pour charger des associations vers d'autres
|
||||
entités et collections.
|
||||
</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>List cats = sess.createSQLQuery(
|
||||
"select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
|
||||
)
|
||||
<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("kitten", "cat.kittens")
|
||||
.list();</programlisting>
|
||||
.addJoin("cat.dog");
|
||||
]]></programlisting>
|
||||
|
||||
<para>
|
||||
Une requête SQL native pourrait retourner une simple valeur scalaire ou une combinaison de scalaires et d'entités.
|
||||
</para>
|
||||
<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>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)
|
||||
<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)
|
||||
.setLong("catId", catId)
|
||||
.list();</programlisting>
|
||||
.addJoin("cat.dogs");
|
||||
]]></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> !
|
||||
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>
|
||||
|
||||
<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>
|
||||
<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>Noms d'injection d'alias</title>
|
||||
<title>Alias injection names</title>
|
||||
|
||||
<tgroup cols="4">
|
||||
<tgroup cols="3">
|
||||
<colspec colwidth="1*" />
|
||||
|
||||
<colspec colwidth="1*" />
|
||||
|
@ -149,23 +253,23 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
<row>
|
||||
<entry>Description</entry>
|
||||
|
||||
<entry>Syntaxe</entry>
|
||||
<entry>Syntax</entry>
|
||||
|
||||
<entry>Exemple</entry>
|
||||
<entry>Example</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Une simple propriété</entry>
|
||||
<entry>A simple property</entry>
|
||||
|
||||
<entry><literal>{[aliasname].[propertyname]}</literal></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>A composite property</entry>
|
||||
|
||||
<entry><literal>{[aliasname].[componentname].[propertyname]}</literal></entry>
|
||||
|
||||
|
@ -174,7 +278,7 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
</row>
|
||||
|
||||
<row>
|
||||
<entry>Discriminant d'une entité</entry>
|
||||
<entry>Discriminator of an entity</entry>
|
||||
|
||||
<entry><literal>{[aliasname].class}</literal></entry>
|
||||
|
||||
|
@ -182,7 +286,7 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
</row>
|
||||
|
||||
<row>
|
||||
<entry>Toutes les propriétés d'une entité</entry>
|
||||
<entry>All properties of an entity</entry>
|
||||
|
||||
<entry><literal>{[aliasname].*}</literal></entry>
|
||||
|
||||
|
@ -190,7 +294,7 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
</row>
|
||||
|
||||
<row>
|
||||
<entry>Une clef de collection</entry>
|
||||
<entry>A collection key</entry>
|
||||
|
||||
<entry><literal>{[aliasname].key}</literal></entry>
|
||||
|
||||
|
@ -198,7 +302,7 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
</row>
|
||||
|
||||
<row>
|
||||
<entry>L'identifiant d'une collection</entry>
|
||||
<entry>The id of an collection</entry>
|
||||
|
||||
<entry><literal>{[aliasname].id}</literal></entry>
|
||||
|
||||
|
@ -206,17 +310,15 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
</row>
|
||||
|
||||
<row>
|
||||
<entry>L'élément d'une collection</entry>
|
||||
<entry>The element of an 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>roperty of the element in the collection</entry>
|
||||
|
||||
<entry><literal>{[aliasname].element.[propertyname]}</literal></entry>
|
||||
|
||||
|
@ -224,7 +326,7 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
</row>
|
||||
|
||||
<row>
|
||||
<entry>Toutes les propriétés de l'élément dans la collection</entry>
|
||||
<entry>All properties of the element in the collection</entry>
|
||||
|
||||
<entry><literal>{[aliasname].element.*}</literal></entry>
|
||||
|
||||
|
@ -232,7 +334,7 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
</row>
|
||||
|
||||
<row>
|
||||
<entry>Toutes les propriétés de la collection</entry>
|
||||
<entry>All properties of the the collection</entry>
|
||||
|
||||
<entry><literal>{[aliasname].*}</literal></entry>
|
||||
|
||||
|
@ -241,7 +343,58 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</sect1>
|
||||
</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>
|
||||
|
||||
<sect1 id="querysql-namedqueries" revision="3">
|
||||
<title>Requêtes SQL nommées</title>
|
||||
|
@ -252,19 +405,19 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
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"/>
|
||||
<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>
|
||||
</sql-query>]]></programlisting>
|
||||
|
||||
<programlisting>List people = sess.getNamedQuery("persons")
|
||||
<programlisting><![CDATA[List people = sess.getNamedQuery("persons")
|
||||
.setString("namePattern", namePattern)
|
||||
.setMaxResults(50)
|
||||
.list();</programlisting>
|
||||
.list();]]></programlisting>
|
||||
|
||||
<para>
|
||||
Les éléments <literal><return-join></literal> et
|
||||
|
@ -272,9 +425,9 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
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"/>
|
||||
<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},
|
||||
|
@ -286,20 +439,20 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
JOIN ADDRESS address
|
||||
ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
|
||||
WHERE person.NAME LIKE :namePattern
|
||||
</sql-query></programlisting>
|
||||
</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"/>
|
||||
<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>
|
||||
</sql-query>]]></programlisting>
|
||||
|
||||
<para>
|
||||
Vous pouvez externaliser les informations de mapping des résultats dans un
|
||||
|
@ -308,12 +461,12 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
<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">
|
||||
<sql-query name="personsWith" resultset-ref="personAddress">
|
||||
SELECT person.NAME AS {person.name},
|
||||
person.AGE AS {person.age},
|
||||
person.SEX AS {person.sex},
|
||||
|
@ -325,7 +478,15 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
JOIN ADDRESS address
|
||||
ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
|
||||
WHERE person.NAME LIKE :namePattern
|
||||
</sql-query></programlisting>
|
||||
</sql-query>]]></programlisting>
|
||||
<para>You can alternatively use the resultset mapping information in your
|
||||
hbm files directly in java code.</para>
|
||||
|
||||
<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 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
<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>
|
||||
<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>
|
||||
</sql-query>
|
||||
]]></programlisting>
|
||||
|
||||
<para>
|
||||
<literal><return-property></literal> fonctionne aussi avec de
|
||||
|
@ -355,21 +516,22 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
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>
|
||||
|
||||
<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>
|
||||
</sql-query>]]></programlisting>
|
||||
|
||||
<para>
|
||||
Notez que dans cet exemple nous avons utilisé <literal><return-property></literal>
|
||||
|
@ -396,36 +558,37 @@ List loggedCats = sess.createSQLQuery(sql)
|
|||
version supérieure :
|
||||
</para>
|
||||
|
||||
<programlisting>CREATE OR REPLACE FUNCTION selectAllEmployments
|
||||
<programlisting><![CDATA[CREATE OR REPLACE FUNCTION selectAllEmployments
|
||||
RETURN SYS_REFCURSOR
|
||||
AS
|
||||
AS
|
||||
st_cursor SYS_REFCURSOR;
|
||||
BEGIN
|
||||
BEGIN
|
||||
OPEN st_cursor FOR
|
||||
SELECT EMPLOYEE, EMPLOYER,
|
||||
STARTDATE, ENDDATE,
|
||||
REGIONCODE, EID, VALUE, CURRENCY
|
||||
FROM EMPLOYMENT;
|
||||
RETURN st_cursor;
|
||||
END;</programlisting>
|
||||
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>
|
||||
<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>
|
||||
</sql-query>]]></programlisting>
|
||||
|
||||
<para>
|
||||
Notez que les procédures stockées retournent, pour le moment, seulement des
|
||||
|
@ -447,7 +610,10 @@ BEGIN
|
|||
|
||||
<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 @@ BEGIN
|
|||
<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 @@ BEGIN
|
|||
|
||||
<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,9 +703,10 @@ BEGIN
|
|||
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)
|
||||
|
||||
<programlisting><![CDATA[CREATE OR REPLACE FUNCTION updatePerson (uid IN NUMBER, uname IN VARCHAR2)
|
||||
RETURN NUMBER IS
|
||||
BEGIN
|
||||
BEGIN
|
||||
|
||||
update PERSON
|
||||
set
|
||||
|
@ -548,7 +716,7 @@ BEGIN
|
|||
|
||||
return SQL%ROWCOUNT;
|
||||
|
||||
END updatePerson;</programlisting>
|
||||
END updatePerson;]]></programlisting>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="querysql-load">
|
||||
|
@ -556,53 +724,52 @@ END updatePerson;</programlisting>
|
|||
|
||||
<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"/>
|
||||
|
||||
<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>
|
||||
</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><class name="Person">
|
||||
<id name="id">
|
||||
<generator class="increment"/>
|
||||
</id>
|
||||
<property name="name" not-null="true"/>
|
||||
<loader query-ref="person"/>
|
||||
</class></programlisting>
|
||||
<programlisting><![CDATA[<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><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"/>
|
||||
<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>
|
||||
</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"/>
|
||||
<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>
|
||||
</sql-query>]]></programlisting>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
|
|
@ -95,6 +95,30 @@ Long generatedId = (Long) sess.save(fritz);]]></programlisting>
|
|||
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
|
||||
surchargée de <literal>save()</literal>.
|
||||
|
@ -478,6 +502,13 @@ List cats = q.list();]]></programlisting>
|
|||
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>
|
||||
|
||||
|
|
|
@ -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 @@ new SchemaExport(cfg).create(false, true);]]></programlisting>
|
|||
</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 @@ new SchemaExport(cfg).create(false, true);]]></programlisting>
|
|||
<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>
|
||||
|
|
|
@ -800,7 +800,12 @@ catch (RuntimeException e) {
|
|||
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">
|
||||
|
|
|
@ -681,7 +681,9 @@ public class EventManager {
|
|||
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 @@ public class EventManager {
|
|||
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 @@ else if (args[0].equals("list")) {
|
|||
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 @@ public void removeFromEvent(Event event) {
|
|||
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">
|
||||
|
@ -1307,25 +1330,16 @@ public void removeFromEvent(Event event) {
|
|||
|
||||
<programlisting><![CDATA[package events;
|
||||
|
||||
// Imports
|
||||
// Imports
|
||||
|
||||
public class EventManagerServlet extends HttpServlet {
|
||||
|
||||
private final SimpleDateFormat dateFormatter =
|
||||
new SimpleDateFormat("dd.MM.yyyy");
|
||||
public class EventManagerServlet extends HttpServlet {
|
||||
|
||||
// Servlet code
|
||||
}]]></programlisting>
|
||||
}]]></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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
La servlet n'accepte que les requêtes HTTP <literal>GET</literal>, la méthode à implémenter est donc
|
||||
<literal>doGet()</literal>:
|
||||
The servlet handles HTTP <literal>GET</literal> requests only, hence, the method
|
||||
we implement is <literal>doGet()</literal>:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[protected void doGet(HttpServletRequest request,
|
||||
|
@ -1359,7 +1373,12 @@ public class EventManagerServlet extends HttpServlet {
|
|||
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.
|
||||
|
|
Loading…
Reference in New Issue