From: <tu...@us...> - 2003-04-22 20:28:19
|
Update of /cvsroot/hibernate/Hibernate2/doc/reference/src In directory sc8-pr-cvs1:/tmp/cvs-serv24130/src Modified Files: manipulating_data.xml Log Message: Integrated first set of FAQs Index: manipulating_data.xml =================================================================== RCS file: /cvsroot/hibernate/Hibernate2/doc/reference/src/manipulating_data.xml,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** manipulating_data.xml 22 Apr 2003 11:11:35 -0000 1.7 --- manipulating_data.xml 22 Apr 2003 20:28:14 -0000 1.8 *************** *** 491,494 **** --- 491,565 ---- secondSession.saveOrUpdate(mate); // save the new instance (mate has a null id)]]></programlisting> + <para> + The usage and semantics of <literal>saveOrUpdate()</literal> seems to be confusing + for new users. Firstly, so long as you are not trying to use instances from one session + in another new session, you should not need to use <literal>update()</literal> or + <literal>saveOrUpdate()</literal>. Some whole applications will never use either of + these methods. + </para> + + <para> + Usually <literal>update()</literal> or <literal>saveOrUpdate()</literal> are used in + the following scenario: + </para> + + <itemizedlist spacing="compact"> + <listitem> + <para> + the application loads an object in the first session + </para> + </listitem> + <listitem> + <para> + the object is passed up to the UI tier + </para> + </listitem> + <listitem> + <para> + some modifications are made to the object + </para> + </listitem> + <listitem> + <para> + the object is passed back down to the business logic tier + </para> + </listitem> + <listitem> + <para> + the application persists these modifications by calling + <literal>update()</literal> in a second session + </para> + </listitem> + </itemizedlist> + + <para> + <literal>saveOrUpdate()</literal> does the following: + </para> + + <itemizedlist spacing="compact"> + <listitem> + <para> + if the object is already persistent in this session, do nothing + </para> + </listitem> + <listitem> + <para> + if the object has no identifier property, <literal>save()</literal> it + </para> + </listitem> + <listitem> + <para> + if the object's identifier matches the criteria specified by + <literal>unsaved-value</literal>, <literal>save()</literal> it + </para> + </listitem> + <listitem> + <para> + if another object associated with the session has the same + identifier, throw an exception + </para> + </listitem> + </itemizedlist> + </sect1> *************** *** 751,755 **** Ending a session involves four distinct phases: </para> ! <itemizedlist spacing="compact"> <listitem> --- 822,826 ---- Ending a session involves four distinct phases: </para> ! <itemizedlist spacing="compact"> <listitem> *************** *** 946,950 **** </sect1> ! <sect1 id="manipulating-data-s15"> <title>Interceptors</title> --- 1017,1021 ---- </sect1> ! <sect1 id="manipulating-data-s15"> <title>Interceptors</title> *************** *** 1047,1050 **** --- 1118,1291 ---- <programlisting><![CDATA[Session session = sf.openSession( new AuditInterceptor() );]]></programlisting> + </sect1> + + <sect1 id="manipulating-data-s16"> + <title>Frequently Asked Questions</title> + + <para> + <emphasis role="strong"> + I saved/deleted/updated an object/collection but I can't see the changes in the database. + </emphasis> + </para> + <para> + You must either call <literal>Transaction.commit()</literal> (if using the Hibernate + Transaction API) or <literal>Session.flush()</literal> at the end of a session to + flush your changes to the database. A commit of the transaction automatically flushes + the state of the current session to the database. + </para> + <para> + If you are not using the Hibernate Transaction API (with + <literal>Session.beginTransaction()</literal>, you must then explicitly commit the + transaction (by committing the JTA transaction or JDBC <literal>Connection</literal>). + </para> + + + <para> + <emphasis role="strong"> + I saved a parent object but its associated objects weren't saved to the database. + </emphasis> + </para> + <para> + Hibernate doesn't support full Persistence By Reachability (automatic cascading + of state changes to reachable objects). Associated objects must be saved explicitly + (by calling <literal>Session.save()</literal>) or the association must be + mapped with <literal>cascade="all"</literal>. + </para> + + + <para> + <emphasis role="strong"> + I'm having trouble with a bidirectional association. + </emphasis> + </para> + <para> + When you update a bidirectional association you must update both ends + (even the one marked <literal>inverse="true"</literal>). This is exactly + the same as with any bidirectional assocation in Java without persistent + objects. + </para> + <programlisting><![CDATA[parent.getChildren().add(child); + child.setParent(parent);]]></programlisting> + + + <para> + <emphasis role="strong"> + I'm seeing foreign key constraint violations when using assigned identifiers + with cascades or <literal>saveOrUpdate()</literal>. + </emphasis> + </para> + <para> + Assigned identifiers and composite identifiers can't be used to distinguish + newly instantiated instances from instances saved or loaded in a + previous session. You will need to be more explicit; tell Hibernate exactly + what you mean by calling either <literal>save()</literal> or + <literal>update()</literal>. + </para> + + + <para> + <emphasis role="strong"> + Hibernate keeps deleting and recreating my collection! + </emphasis> + </para> + <para> + Unlike other Hibernate value types, Hibernate tracks actual collection + instances using Java identity, <literal>==</literal>. Your getter method should + return the same collection instance as was assigned by Hibernate to the setter + method (unless you don't mind the collection being removed and recreated every + time the session is flushed). + </para> + <para> + This doesn't mean you shouldn't return a different collection if you really + are replacing the current collection with a new collection with completely + different elements. In certain cases, this behaviour can even be taken + advantage of to increase performance. + </para> + + + <para> + <emphasis role="strong"> + Hibernate throws a <literal>NullPointerException</literal> when I load or query an object. + </emphasis> + </para> + <para> + If your object has a primitive-type property mapped to a nullable database column then + you will need to use a Hibernate custom type to assign a sensible default + (primitive) value for the case of a null column value. A better solution is usually to + use a wrapper type for the Java property (ie. Long, Integer, ...). + </para> + + <para> + <emphasis role="strong"> + I removed an object from a collection mapped with <literal>cascade="all"</literal> + but the object was not deleted! + </emphasis> + </para> + <para> + When marked as <literal>cascade="all"</literal>, Hibernate cascades the + <literal>delete()</literal> operation from parent to child. Hibernate never deletes + an entity without this implicit or an explicit call to <literal>delete()</literal>. + If you aren't deleting the parent object, you will have to explicitly delete + the child after you've removed it from the collection. + </para> + <para> + On the other hand, if you really want to avoid explicitly deleting collection + elements, one solution is to model them as value types rather than + entities. (Value types are always persisted or removed along with their + parent entity.) So you would use a <literal><composite-element></literal> + mapping for the element class instead of modelling it as a seperate entity. + </para> + + + <para> + <emphasis role="strong"> + <literal>saveOrUpdate()</literal> just creates new rows for old instances! + </emphasis> + </para> + <para> + There are two reasons why this could occur: + </para> + <itemizedlist spacing="compact"> + <listitem> + <para> + The <literal><id></literal> element does not specify the + correct <literal>unsaved-value</literal>. + </para> + </listitem> + <listitem> + <para> + You are using an <literal>assigned</literal> identifier + (or a composite identifier). + </para> + </listitem> + </itemizedlist> + <para> + In the first case, you should simply specify <literal>unsaved-value</literal>. + In the second case, you can't use <literal>saveOrUpdate()</literal>. You should + explicitly call <literal>save()</literal> or <literal>update()</literal> on a + case-by-case basis. + </para> + + + <para> + <emphasis role="strong"> + Why does Hibernate always initialize a collection when I only want to add or + remove an element? + </emphasis> + </para> + <para> + Unfortunately the collections API defines method return values that may + only be computed by hitting the database. (There is one exception to this: + Hibernate can add to a <literal><bag></literal> declared with + <literal>readonly="true"</literal> without initializing the bag; the return + value must always be true.) + </para> + <para> + If you want to avoid this extra database traffic (ie. in performance critical + code), refactor your model to use only many-to-one associations. This is + almost always possible. Then use queries in place of collection access. + </para> + + </sect1> |