From: <tu...@us...> - 2003-04-26 01:42:33
|
Update of /cvsroot/hibernate/Hibernate2/doc/reference/src In directory sc8-pr-cvs1:/tmp/cvs-serv4472/src Modified Files: advanced_or_mapping.xml basic_or_mapping.xml Log Message: Integrated some more FAQ items Index: advanced_or_mapping.xml =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/doc/reference/src/advanced_or_mapping.xml,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** advanced_or_mapping.xml 19 Apr 2003 03:34:34 -0000 1.17 --- advanced_or_mapping.xml 26 Apr 2003 01:42:29 -0000 1.18 *************** *** 200,204 **** </calloutlist> </programlistingco> ! </sect2> --- 200,235 ---- </calloutlist> </programlistingco> ! ! <para> ! The mapping of a List or array requires a seperate table column holding the array or List index ! (the <literal>i</literal> in <literal>foo[i]</literal>). If your relational model doesn't have ! an index column, e.g. if you're working with legacy data, use an unordered <literal>Set</literal> ! instead. This seems to put people off who assume that <literal>List</literal> should just be a ! more convenient way of accessing an unordered collection. Hibernate collections strictly obey ! the actual semantics attached to the <literal>Set</literal>, <literal>List</literal> and ! <literal>Map</literal> interfaces. <literal>List</literal> elements don't just spontaneously ! rearrange themselves. ! </para> ! ! <para> ! On the other hand, people who planned to use the <literal>List</literal> to emulate "bag"-style ! semantics have a legitimate grievance here. Fortunately you can map a <literal>List</literal> ! or <literal>Collection</literal> with bag semantics. ! </para> ! ! <para> ! A bag is an unordered, unindexed collection which can contain the same element multiple times. ! The Java collections framework lacks a <literal>Bag</literal> interface (though you can emulat ! it with a <literal>List</literal>). Hibernate lets you map properties of type <literal>List</literal> ! or <literal>Collection</literal> with the <literal><bag></literal> element. Note that bag ! semantics are not really part of the <literal>Collection</literal> contract and they actually ! conflict with the semantics of <literal>List</literal>. ! </para> ! ! <para> ! Large Hibernate bags are inefficient and should be avoided, Hibernate can't create, delete or ! update rows individually with such a mapping. ! </para> ! </sect2> *************** *** 293,297 **** <listitem> <para> ! No null values may be contained in a map or set </para> </listitem> --- 324,328 ---- <listitem> <para> ! No null values may be contained in a map, set or list </para> </listitem> *************** *** 333,336 **** --- 364,376 ---- The <literal>one-to-many</literal> tag does not need to declare any columns. </para> + + <para> + If the <literal>key</literal> column in the database is declared as + <literal>NOT NULL</literal>, Hibernate may cause constraint violations. + To prevent this, you must use a bidirectional association with the many-end + (the set, bag, list or map) marked as <literal>inverse="true"</literal> to + ensure the correct order of updates in the database. + </para> + </sect2> *************** *** 378,382 **** <para> ! Declare a lazy collection using the optional <literal>lazy</literal> attribute </para> --- 418,422 ---- <para> ! Declare a lazy collection using the optional <literal>lazy</literal> attribute: </para> *************** *** 386,389 **** --- 426,494 ---- </set>]]></programlisting> + <para> + As we already mentioned, the <literal>Session</literal> must not be committed + nor closed when a collection is initialized. This can be confusing for new + Hibernate users, as a first approach would abstract the data access logic from + the upper layers of the application. With this kind of architecture, an + uninitialized collection may be returned from a method of the data access + class while the <literal>Session</literal> is already committed and closed in + that returning method. They are several ways to deal with this issue: + </para> + + <itemizedlist> + <listitem> + <para> + In a web-based application, a Servlet Filter can be used to finally + close the <literal>Session</literal> when the rendering of the + View has completed. Of course, it can be difficult to ensure that + the <literal>Session</literal> is rolled backed if an exception + occours during the rendering of the View. The Servlet Filter has to + know about the <literal>Session</literal> for this approach: A + <literal>ThreadLocal</literal> variable can be used to hold the + current <literal>Session</literal> of a thread during execution. + That way, a Servlet Filter can open (or <literal>reconnect()</literal>) + a <literal>Session</literal> when a new HTTP request arrives, place + the <literal>Session</literal> in a <literal>ThreadLocal</literal> + variable and lateron close (or <literal>disconnect()</literal> and store + it in the users <literal>HttpSession</literal>) the + <literal>Session</literal> when the request has been successfuly executed. + The data access classes obtain the current <literal>Session</literal> + from the <literal>ThreadLocal</literal> variable. This setup is best + wrapped with helper and utility classes (ie. a class for Hibernate + <literal>Session</literal> management). + </para> + </listitem> + <listitem> + <para> + If the application is not web-based and has no distinct rendering of + a View, the usage of a <literal>ThreadLocal</literal> can be adapted + as required (replacing the Servlet Filter with another request/response + based filter class). + </para> + </listitem> + <listitem> + <para> + The data access class can provide methods that start and end + units of work like <literal>dao.beginUOW()</literal> and + <literal>dao.endUOW()</literal> which would internally open and close + a <literal>Session</literal>. This is no different from re-using a single + JDBC <literal>Connection</literal> during multiple method calls on a + standard data access object in an non-managed environment with explicit + transaction management by the user. + </para> + </listitem> + <listitem> + <para> + Hibernate can initialize collections itself with a call to + <literal>Hibernate.initialize(Object object)</literal>. Keep in mind + though, that the <literal>Session</literal> which was used to lazily + load the collection must still be open when it is initialized. This method + is primarily used in a data access class to initialize a known subset of + collections before the whole object containing that collections is returned + to the caller and the <literal>Session</literal> is closed. + </para> + </listitem> + </itemizedlist> + </sect2> *************** *** 415,418 **** --- 520,532 ---- <literal>java.util.TreeMap</literal>. </para> + + <para> + Another approach is to use the <literal>order-by</literal> attribute of either + <literal>set</literal>, <literal>map</literal> or <literal>list</literal> mappings. + This solution is only available with JDK 1.4 or higher. Please note that a collection + can be be sorted arbitrary at runtime by a the <literal>filter()</literal> method of the + Hibernate Session API. + </para> + </sect2> *************** *** 444,448 **** <listitem> <para> ! Set valued at one end, single-valued at the other </para> </listitem> --- 558,562 ---- <listitem> <para> ! Set/Bag/List/Map valued at one end, single-valued at the other </para> </listitem> *************** *** 452,456 **** <listitem> <para> ! Set/bag valued at both ends </para> </listitem> --- 566,570 ---- <listitem> <para> ! Set/Bag/List/Map valued at both ends </para> </listitem> *************** *** 506,509 **** --- 620,643 ---- <many-to-one name="parent" class="eg.Parent" column="parent_id"/> </class>]]></programlisting> + + <para> + Mapping one end of an association with <literal>inverse="true"</literal> doesn't + affect the cascading of operations. The <literal>inverse="true"</literal> marks + one end of an association as "bidirectional". Of course, this happens with the + mapping the assocation itself, ie. if the many-end is mapped as a + <literal>set</literal>. But Hibernate can optimize the semantics of an update of + the bidirectional association when marked with the <literal>inverse="true"</literal> + attribute, ie. the ordering of <literal>UPDATE</literal> statements executed on + the database. The multi-valued end of a one-to-many association has always to be + marked with <literal>inverse="true"</literal> if the association is bidirectional. + </para> + + <para> + The <literal>cascade="all"</literal> simply marks the cascading of calls to + <literal>save()</literal>, <literal>update()</literal>, <literal>delete()</literal>, + etc. It doesn't interact in any way with the <literal>inverse="true"</literal> mapping, + both concepts are orthogonal. + </para> + </sect2> Index: basic_or_mapping.xml =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/doc/reference/src/basic_or_mapping.xml,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** basic_or_mapping.xml 24 Apr 2003 09:23:12 -0000 1.16 --- basic_or_mapping.xml 26 Apr 2003 01:42:29 -0000 1.17 *************** *** 211,215 **** It is perfectly acceptable for the named persistent class to be an interface. You would then declare implementing classes of that interface using the <literal><subclass></literal> ! element. </para> --- 211,216 ---- It is perfectly acceptable for the named persistent class to be an interface. You would then declare implementing classes of that interface using the <literal><subclass></literal> ! element. You may persist any <emphasis>static</emphasis> inner class. You should specify the ! class name using the standard form ie. <literal>eg.Foo$Bar</literal>. </para> *************** *** 834,837 **** --- 835,856 ---- <literal>Hibernate.TIMESTAMP</literal>, or to specify a custom type.) </para> + + <para> + If you want to customize the database type of the generated SQL DDL (when using + the Hibernate toolset to generate the schema), you can set the appropriate type + with the <literal>sql-type</literal> attribute of the + <literal><column></literal> element (in addition to the <literal>column</literal> + name attribute of the <literal>property</literal>). This element has several other + attributes related to automatic schema generation: + </para> + + <programlisting><![CDATA[<property name="amount" type="big_decimal"> + <column sql-type="NUMERIC(11, 2)" not-null="true"/> + </property> + + <property name="socialsecuritynumber" type="string"> + <column sql-type="CHAR" length="9" not-null="true" unique="true"/> + </property>]]></programlisting> + </sect2> *************** *** 1588,1592 **** </sect1> - </chapter> --- 1607,1610 ---- |