| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <title xmlns:d="http://docbook.org/ns/docbook">Chapter 6. Getting started with persistent objects</title><link rel="stylesheet" type="text/css" href="css/cayenne-doc.css"><meta xmlns:d="http://docbook.org/ns/docbook" name="keywords" content="Cayenne 3.1 documentation"><meta xmlns:d="http://docbook.org/ns/docbook" name="description" content="User documentation for Apache Cayenne version 3.1"><link rel="home" href="index.html" title="Getting Started with Cayenne"><link rel="up" href="getting-started-part3.html" title="Part III. Learning Cayenne API"><link rel="prev" href="ch05.html" title="Chapter 5. Getting started with ObjectContext"><link rel="next" href="ch07.html" title="Chapter 7. Selecting Objects"><script xmlns:d="http://docbook.org/ns/docbook" type="text/javascript"> |
| var _gaq = _gaq || []; |
| _gaq.push(['_setAccount', 'UA-7036673-1']); |
| _gaq.push(['_trackPageview']); |
| (function() { |
| var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
| ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
| var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
| })(); |
| </script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div xmlns:d="http://docbook.org/ns/docbook" class="navheader"><table width="100%" summary="Navigation header"><tr><th class="versioninfo">v.3.1 (3.1)</th><th align="center">Chapter 6. Getting started with persistent objects</th><th></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch05.html">Prev</a> </td><th width="60%" align="center"><a accesskey="u" href="getting-started-part3.html">Part III. Learning Cayenne API</a></th><td width="20%" align="right"> <a accesskey="n" href="ch07.html">Next</a></td></tr></table><hr></div><div class="chapter" title="Chapter 6. Getting started with persistent objects"><div class="titlepage"><div><div><h2 class="title"><a name="d0e361"></a>Chapter 6. Getting started with persistent objects</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="ch06.html#customizing-persistent-objects">Inspecting and Customizing Persistent Objects</a></span></dt><dt><span class="section"><a href="ch06.html#create-new-objects">Create New Objects</a></span></dt></dl></div><p>In this chapter we'll learn about persistent objects, how to customize them and how to |
| create and save them in DB.</p><div class="section" title="Inspecting and Customizing Persistent Objects"><div class="titlepage"><div><div><h2 class="title"><a name="customizing-persistent-objects"></a>Inspecting and Customizing Persistent Objects</h2></div></div></div><p>Persistent classes in Cayenne implement a DataObject interface. If you inspect any of |
| the classes generated earlier in this tutorial (e.g. |
| org.example.cayenne.persistent.Artist), you'll see that it extends a class with the name |
| that starts with underscore (org.example.cayenne.persistent.auto._Artist), which in turn |
| extends from org.apache.cayenne.CayenneDataObject. Splitting each persistent class into |
| user-customizable subclass (Xyz) and a generated superclass (_Xyz) is a useful technique |
| to avoid overwriting the custom code when refreshing classes from the mapping |
| model.</p><p>Let's for instance add a utility method to the Artist class that sets Artist date of |
| birth, taking a string argument for the date. It will be preserved even if the model |
| changes later:</p><pre class="programlisting"><span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">package</span> org.example.cayenne.persistent; |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">import</span> java.text.ParseException; |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">import</span> java.text.SimpleDateFormat; |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">import</span> java.util.Date; |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">import</span> org.example.cayenne.persistent.auto._Artist; |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">public</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span> Artist <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">extends</span> _Artist { |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">static</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">final</span> String DEFAULT_DATE_FORMAT = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"yyyyMMdd"</span>; |
| |
| <strong xmlns="http://www.w3.org/1999/xhtml" class="hl-tag">/** |
| * Sets date of birth using a string in format yyyyMMdd. |
| */</strong> |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">public</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">void</span> setDateOfBirthString(String yearMonthDay) { |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">if</span> (yearMonthDay == null) { |
| setDateOfBirth(null); |
| } <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">else</span> { |
| |
| Date date; |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">try</span> { |
| date = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> SimpleDateFormat(DEFAULT_DATE_FORMAT) |
| .parse(yearMonthDay); |
| } <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">catch</span> (ParseException e) { |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">throw</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> IllegalArgumentException( |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"A date argument must be in format '"</span> |
| + DEFAULT_DATE_FORMAT + <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"': "</span> + yearMonthDay); |
| } |
| |
| setDateOfBirth(date); |
| } |
| } |
| }</pre></div><div class="section" title="Create New Objects"><div class="titlepage"><div><div><h2 class="title"><a name="create-new-objects"></a>Create New Objects</h2></div></div></div><p>Now we'll create a bunch of objects and save them to the database. An object is |
| created and registered with ObjectContext using "newObject" method. Objects <span class="bold"><strong>must</strong></span> be registered with DataContext to be persisted and to |
| allow setting relationships with other objects. Add this code to the "main" method of |
| the Main class:</p><pre class="programlisting">Artist picasso = context.newObject(Artist.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>); |
| picasso.setName(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Pablo Picasso"</span>); |
| picasso.setDateOfBirthString(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"18811025"</span>);</pre><p>Note that at this point "picasso" object is only stored in memory and is not saved in |
| the database. Let's continue by adding a Metropolitan Museum "Gallery" object and a few |
| Picasso "Paintings":</p><pre class="programlisting">Gallery metropolitan = context.newObject(Gallery.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>); |
| metropolitan.setName(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Metropolitan Museum of Art"</span>); |
| |
| Painting girl = context.newObject(Painting.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>); |
| girl.setName(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Girl Reading at a Table"</span>); |
| |
| Painting stein = context.newObject(Painting.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>); |
| stein.setName(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Gertrude Stein"</span>);</pre><p>Now we can link the objects together, establishing relationships. Note that in each |
| case below relationships are automatically estabslished in both directions (e.g. |
| picasso.addToPaintings(girl) has exactly the same effect as |
| girl.setToArtist(picasso)).</p><pre class="programlisting">picasso.addToPaintings(girl); |
| picasso.addToPaintings(stein); |
| |
| girl.setGallery(metropolitan); |
| stein.setGallery(metropolitan);</pre><p>Now lets save all five new objects, in a single method call:</p><pre class="programlisting">context.commitChanges();</pre><p>Now you can run the application again as described in the previous chapter. The new |
| output will show a few actual DB operations:</p><pre class="programlisting">org.apache.cayenne.configuration.XMLDataChannelDescriptorLoader load |
| INFO: Loading XML configuration resource from file:cayenne-project.xml |
| ... |
| INFO: Opening connection: jdbc:derby:memory:testdb;create=true |
| Login: null |
| Password: ******* |
| INFO: +++ Connecting: SUCCESS. |
| INFO: Detected and installed adapter: org.apache.cayenne.dba.derby.DerbyAdapter |
| INFO: --- transaction started. |
| INFO: No schema detected, will create mapped tables |
| INFO: CREATE TABLE GALLERY (ID INTEGER NOT NULL, NAME VARCHAR (200), PRIMARY KEY (ID)) |
| INFO: CREATE TABLE ARTIST (DATE_OF_BIRTH DATE, ID INTEGER NOT NULL, NAME VARCHAR (200), PRIMARY KEY (ID)) |
| INFO: CREATE TABLE PAINTING (ARTIST_ID INTEGER, GALLERY_ID INTEGER, ID INTEGER NOT NULL, |
| NAME VARCHAR (200), PRIMARY KEY (ID)) |
| INFO: ALTER TABLE PAINTING ADD FOREIGN KEY (ARTIST_ID) REFERENCES ARTIST (ID) |
| INFO: ALTER TABLE PAINTING ADD FOREIGN KEY (GALLERY_ID) REFERENCES GALLERY (ID) |
| INFO: CREATE TABLE AUTO_PK_SUPPORT ( |
| TABLE_NAME CHAR(100) NOT NULL, NEXT_ID BIGINT NOT NULL, PRIMARY KEY(TABLE_NAME)) |
| INFO: DELETE FROM AUTO_PK_SUPPORT WHERE TABLE_NAME IN ('ARTIST', 'GALLERY', 'PAINTING') |
| INFO: INSERT INTO AUTO_PK_SUPPORT (TABLE_NAME, NEXT_ID) VALUES ('ARTIST', 200) |
| INFO: INSERT INTO AUTO_PK_SUPPORT (TABLE_NAME, NEXT_ID) VALUES ('GALLERY', 200) |
| INFO: INSERT INTO AUTO_PK_SUPPORT (TABLE_NAME, NEXT_ID) VALUES ('PAINTING', 200) |
| INFO: SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = ? FOR UPDATE [bind: 1:'ARTIST'] |
| INFO: SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = ? FOR UPDATE [bind: 1:'GALLERY'] |
| INFO: SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = ? FOR UPDATE [bind: 1:'PAINTING'] |
| INFO: INSERT INTO GALLERY (ID, NAME) VALUES (?, ?) |
| INFO: [batch bind: 1->ID:200, 2->NAME:'Metropolitan Museum of Art'] |
| INFO: === updated 1 row. |
| INFO: INSERT INTO ARTIST (DATE_OF_BIRTH, ID, NAME) VALUES (?, ?, ?) |
| INFO: [batch bind: 1->DATE_OF_BIRTH:'1881-10-25 00:00:00.0', 2->ID:200, 3->NAME:'Pablo Picasso'] |
| INFO: === updated 1 row. |
| INFO: INSERT INTO PAINTING (ARTIST_ID, GALLERY_ID, ID, NAME) VALUES (?, ?, ?, ?) |
| INFO: [batch bind: 1->ARTIST_ID:200, 2->GALLERY_ID:200, 3->ID:200, 4->NAME:'Gertrude Stein'] |
| INFO: [batch bind: 1->ARTIST_ID:200, 2->GALLERY_ID:200, 3->ID:201, 4->NAME:'Girl Reading at a Table'] |
| INFO: === updated 2 rows. |
| INFO: +++ transaction committed. |
| </pre><p>So first Cayenne creates the needed tables (remember, we used |
| "CreateIfNoSchemaStrategy"). Then it runs a number of inserts, generating primary keys |
| on the fly. Not bad for just a few lines of code.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch05.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started-part3.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch07.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 5. Getting started with ObjectContext </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 7. Selecting Objects</td></tr></table></div></body></html> |