<?xml version="1.0"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
-->

<document>
 <properties>
   <title>Torque ORM Reference - Writing to the database</title>
   <author email="leon@opticode.co.za">Leon Messerschmidt</author>
   <author email="jvanzyl@periapt.com">Jason van Zyl</author>
   <author email="seade@backstagetech.com.au">Scott Eade</author>
 </properties>

 <body>
  <section name="Saving an object (inserts and updates)">

    <p>
      To write an object into the database, call its save() method.  Depending 
      on whether the data object was newly created or was read from the
      database, the corresponding row in the database table is inserted or 
      updated.  If the object is new, its primary key(s) is/are generated 
      automatically if the id method was set to &quot;native&quot; or
      &quot;idbroker&quot; in the schema.xml.
    </p>
    
    <p>
      As an example, consider the following code, which creates an Author 
      object and inserts it into the database.
    </p>

<source>
Author stevens = new Author();
stevens.setFirstName("W.");
stevens.setLastName("Stevens");
stevens.save();
</source>
    
    <p>
      If the generator properties &quot;torque.complexObjectModel&quot; and 
      &quot;torque.objectIsCaching&quot; were not set to false at generation 
      time, any objects which are referenced in the foreign key Lists of the
      object are also saved.  
    </p>

    <p>
      For example, in the following code, calling
      book.save() also saves the author added to the book:
    </p>
    
<source>
Author bloch = new Author();
bloch.setFirstName("Joshua");
bloch.setLastName("Bloch");
Book effective = new Book();
effective.setTitle("Effective Java");
effective.setISBN("0-618-12902-2");
effective.setPublisher(addison);
bloch.addBook(effective);
bloch.save(); //also saves the book "effective"
</source>

    <p>
      Note that the save is only propagated in the 1->n directions of foreign 
      keys, not in the n->1 direction. I.e. in the above example, calling 
      <code>effective.save()</code> would NOT save the corresponding author.
    </p>

    <p>
      If the object which save method is called is neither new nor modified,
      it is not saved. Internally, this is handled via the <code>isNew</code>
      and <code>modified</code> flags of the object.
    </p>
      
    <p>
      There are alternative ways to insert or update an object in the database:
      you can pass the objects to the <code>doInsert()</code> or 
      <code>doUpdate()</code> methods of their corresponding Peers, or you can 
      create a ColumnValues object which contains the data of the object
      and pass the Criteria object to the <code>doInsert()</code> or 
      <code>doUpdate()</code> methods of the Peer class.  
      Note that if you construct a ColumnValues object for a new object,
      the id field need not be added to the ColumnValues;
      it is taken care of by Torque internally.
    </p>
  </section>
  
  <section name="Linking objects">
    <p>
      This section is about how to establish foreign-key relations between
      objects. As explained above, if the generator properties 
      &quot;torque.complexObjectModel&quot; and 
      &quot;torque.objectIsCaching&quot; were not set to false at generation 
      time, collection fields will be created for each foreign key in the
      object which is referenced by the foreign key, 
      and objects which are contained in such a collection will also be saved.
      On the other hand, if the referencing object is saved, the referenced
      object will not be saved. This default behavior can be overridden by
      overriding the save methods of the respective objects. 
    </p>
    
    <p>
      To make this more clear, let's consider an example where the table book
      has a foreign key on the table author. This means, a book object
      can reference an author object. In this case, Torque will generate
      a collection of books in the author object which can be accessed by
      the methods <code>getBooks()</code>, <code>addBook()</code>
      and <code>isBooksInitialized()</code>.
      The collection can contain the books referencing the author object.
      Also, in the book object, there are methods <code>getAuthor()</code>
      and <code>setAuthor()</code> which can manipulate the referenced author.
      <br/>
      In the case where we have a new author object, and we add a book object
      to the referencing books via the author's <code>addBook()</code> method
      and then save the author object, the linked book object will be saved
      as well.
      <br/>
      On the other hand, if we have the same situation (a book added to an 
      author via the <code>addBook()</code> method) and then save the book,
      the referenced author will _NOT_ be saved.
      <br/>
      This is because foreign keys often represent a logical tree structure:
      A parent object (in our case author) has potentially many child objects
      (in our case books). If a parent is saved, the children are also saved
      by default, but not the other way round.
    </p>
  </section>

  <section name="Bulk modifying linked objects">
    <p>
      In the tutorial database, the book table has a foreign key
      to the author table. So as discussed above, the author object
      has a collection of books, and books added to this collection get saved
      when the corresponding author object is saved.
      However, this does not mean that the collection of books associated
      to that author is actually synced to the book collection in the author
      object. For example, if books are removed from the author's book 
      collection and the author object is saved afterwards,
      the book is not deleted or unbound from the author,
      it is just disregarded in the save and the collection
      in the author object and the database are out of sync.
    </p>
    <p>
      To provide am simple means of syncing the state of such a collection
      to the database, Torque generates methods to set the state of linked
      objects in an object and the database: the setAndSave methods.
      For example, the AuthorPeer class has a method 
      <code>setAndSaveBooks(Author toLinkTo, Collection&lt;Book&gt; toSave)</code>
      which does the following:
    </p>
    <ul>
      <li>
        The current collection of books which are linked to the author toLinkTo
        and which are also in the list toSave is read from the database
        into the list intersection.
      </li>
      <li>
        All books in toSave which are not in intersection are inserted.
      </li>
      <li>
        All books in intersection which are also in toSave are updated
        with the corresponding values in toSave and saved.
      </li>
      <li>
        All books in the database which are linked to the author but are 
        not in toSave are deleted from the database.
      </li>
    </ul>
    <p>
      After this procedure, the list of books which are linked to the passed
      author object in the database and the cached list of books in the
      passed author object are exactly the passed list of books. 
      This is an easy way to specify the list of linked objects
      in the database; and it is better than just deleting and re-inserting the
      linked books because it preserves primary keys of existing objects
      and does not execute any database writes for unmodified objects.
    </p>
    
  </section>

  <section name="Mass updates">
    <p>
      If you want to update many objects at once, use the 
      doUpdate(Criteria, ColumnValues) method in BasePeer.
      For example, to set the name attribute to null
      for all authors with an id greater than 5, use:
    </p>

<source>
Criteria criteria = new Criteria();
criteria.where(AuthorPeer.AUTHOR_ID, 5, Criteria.GREATER_THAN);
ColumnValues columnValues = new ColumnValues();
columnValues.put(AuthorPeer.NAME,
    new JdbcTypedValue(
        null,
        java.sql.Types.VARCHAR));
BasePeer.doUpdate(criteria, columnValues);
</source>

  </section>
  
  <section name="Deleting objects">
    <p>
      If you want to delete an author which was already loaded into memory,
      then simply pass the object to the doDelete method of the peer:
    </p>

<source>
AuthorPeer.doDelete(author);
</source>

    <p>
      You do not need to load authors to delete them, you can also use a
      Criteria object to perform deletes. For example, to delete the author
      with the id 3 without loading the author object, use:
    </p>

<source>
Criteria criteria = new Criteria();
criteria.where(AuthorPeer.AUTHOR_ID, 3);
AuthorPeer.doDelete(criteria);
</source>

    <p>
      The latter method can also be used for mass deletes. 
      E.g. to delete all authors with an id greater than 5, use: 
    </p>

<source>
Criteria criteria = new Criteria();
criteria.where(AuthorPeer.AUTHOR_ID, 5, Criteria.GREATER_THAN);
AuthorPeer.doDelete(criteria);
</source>

  </section>

  <section name="Default values">
    <p>
      If a default is specified, the default value is used on both
      a new java object and as column default value in the sql script
      for the database.
      However, when a java object is saved, the database value is always
      overwritten because the normal behavior for saving a new object
      is to write all fields.
      This behavior can be overwritten by setting the column attribute
      useDatabaseDefaultValue to true. In this case, the column is not
      written on inserts if the value of the corresponding java field
      is equal to the default.<br/>
      It is a good idea to have a non-primary key field in each table where 
      useDatabaseDefaultValue is not set because otherwise you could run into
      SQL syntax errors when an unchanged new object is changed
      (because there are no values to insert).
    </p>
    <p>
      One can use CURRENT_DATE, CURRENT_TIME and CURRENT_TIMESTAMP
      as default for Date fields.
      Setting the attribute useDatabaseDefaultValue to false
      or not setting it makes Torque use the current java time
      as initial field value when constructing the object
      and saving it to the database, not considering the database default.
      Setting the attribute useDatabaseDefaultValue to true
      makes Torque setting the initial field value to null
      and using the database default when the object is first
      saved to the database.
    </p>
  </section>
 </body>
</document>
