http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started.html ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started.html b/src/main/site/content/docs/4.0/getting-started.html deleted file mode 100644 index a7f2bfc..0000000 --- a/src/main/site/content/docs/4.0/getting-started.html +++ /dev/null @@ -1,1334 +0,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. - -title: "Cayenne 4.0 Getting Started Guide" -description: "Tutorial how to quick start new Cayenne project" -cayenneVersion: "4.0" -menu: - footer: - weight: 20 - parent: docs - name: "Getting Started (4.0)" ---- -<div id="toc" class="toc"> -<div id="toctitle">Table of Contents</div> -<ul class="sectlevel1"> -<li><a href="#setting-up-the-environment">1. Setting up the environment</a> -<ul class="sectlevel2"> -<li><a href="#install-java">1.1. Install Java</a></li> -<li><a href="#install-intellij-idea">1.2. Install IntelliJ IDEA</a></li> -</ul> -</li> -<li><a href="#learning-mapping-basics">2. Learning mapping basics</a> -<ul class="sectlevel2"> -<li><a href="#starting-a-project">2.1. Starting a project</a></li> -<li><a href="#getting-started-with-object-relational-mapping-orm">2.2. Getting started with Object Relational Mapping (ORM)</a></li> -<li><a href="#creating-java-classes">2.3. Creating Java Classes</a></li> -</ul> -</li> -<li><a href="#learning-cayenne-api">3. Learning Cayenne API</a> -<ul class="sectlevel2"> -<li><a href="#getting-started-with-objectcontext">3.1. Getting started with ObjectContext</a></li> -<li><a href="#getting-started-with-persistent-objects">3.2. Getting started with persistent objects</a></li> -<li><a href="#selecting-objects">3.3. Selecting Objects</a></li> -<li><a href="#deleting-objects">3.4. Deleting Objects</a></li> -</ul> -</li> -<li><a href="#converting-to-web-application">4. Converting to Web Application</a> -<ul class="sectlevel2"> -<li><a href="#converting-tutorial-to-a-web-application">4.1. Converting Tutorial to a Web Application</a></li> -</ul> -</li> -</ul> -</div> -<!--more--> -<div id="preamble"> -<div class="sectionbody"> -<div class="paragraph"> -<p><span class="small">Copyright © 2011-2017 Apache Software Foundation and individual authors</span></p> -</div> -<div class="paragraph"> -<div class="title">License</div> -<p><span class="small"><em>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 <a href="http://www.apache.org/licenses/LICENSE-2.0" class="bare">http://www.apache.org/licenses/LICENSE-2.0</a></em></span></p> -</div> -<div class="paragraph"> -<p><span class="small"><em>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.</em></span></p> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="setting-up-the-environment"><a class="anchor" href="#setting-up-the-environment"></a>1. Setting up the environment</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>The goal of this chapter of the tutorial is to install (or check that you already have -installed) a minimally needed set of software to build a Cayenne application.</p> -</div> -<div class="sect2"> -<h3 id="install-java"><a class="anchor" href="#install-java"></a>1.1. Install Java</h3> -<div class="paragraph"> -<p>Obviously, JDK has to be installed. Cayenne 4.0 requires JDK 1.7 or newer.</p> -</div> -</div> -<div class="sect2"> -<h3 id="install-intellij-idea"><a class="anchor" href="#install-intellij-idea"></a>1.2. Install IntelliJ IDEA</h3> -<div class="paragraph"> -<p>Download and install IntelliJ IDEA Community Edition. -This tutorial is based on version 2016.3, still it should work with any recent IntelliJ IDEA version.</p> -</div> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="learning-mapping-basics"><a class="anchor" href="#learning-mapping-basics"></a>2. Learning mapping basics</h2> -<div class="sectionbody"> -<div class="sect2"> -<h3 id="starting-a-project"><a class="anchor" href="#starting-a-project"></a>2.1. Starting a project</h3> -<div class="paragraph"> -<p>The goal of this chapter is to create a new Java project in IntelliJ IDEA -containing a basic Cayenne mapping. It presents an introduction to -CayenneModeler GUI tool, showing how to create the initial mapping -objects: <code>DataDomain</code>, <code>DataNode</code>, <code>DataMap</code>.</p> -</div> -<div class="sect3"> -<h4 id="create-a-new-project-in-intellij-idea"><a class="anchor" href="#create-a-new-project-in-intellij-idea"></a>Create a new Project in IntelliJ IDEA</h4> -<div class="paragraph"> -<p>In IntelliJ IDEA select <code>File > New > Project..</code> and then -select <code>Maven</code> and click <code>Next</code>. -In the dialog shown on the screenshot below, fill the <code>Group Id</code> -and <code>Artifact Id</code> fields and click <code>Next</code>.</p> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/tutorial-idea-project.png" alt="tutorial idea project"> -</div> -</div> -<div class="paragraph"> -<p>On next dialog screen you can customize directory for your project and click <code>Finish</code>. -Now you should have a new empty project.</p> -</div> -</div> -<div class="sect3"> -<h4 id="download-and-start-cayennemodeler"><a class="anchor" href="#download-and-start-cayennemodeler"></a>Download and Start CayenneModeler</h4> -<div class="paragraph"> -<p>Although later in this tutorial we’ll be using Maven to include Cayenne -runtime jars in the project, you’ll still need to download Cayenne to -get access to the CayenneModeler tool.</p> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -If you are really into Maven, you can start CayenneModeler from Maven too. - We’ll do it in a more traditional way here. -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Download the <a href="http://cayenne.apache.org/download.html">latest release</a>. Unpack the distribution -somewhere in the file system and start CayenneModeler, following platform-specific instructions. -On most platforms it is done simply by doubleclicking the Modeler icon. -The welcome screen of the Modeler looks like this:</p> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/modeler-started.png" alt="modeler started"> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="create-a-new-mapping-project-in-cayennemodeler"><a class="anchor" href="#create-a-new-mapping-project-in-cayennemodeler"></a>Create a New Mapping Project in CayenneModeler</h4> -<div class="paragraph"> -<p>Click on the <code>New Project</code> button on Welcome screen. A new mapping project will appear -that contains a single <strong>DataDomain</strong>. The meaning of a -DataDomain is explained elsewhere in the User Guide. For now it is sufficient to -understand that DataDomain is the root of your mapping project.</p> -</div> -</div> -<div class="sect3"> -<h4 id="create-a-datanode"><a class="anchor" href="#create-a-datanode"></a>Create a DataNode</h4> -<div class="paragraph"> -<p>The next project object you will create is a <strong>DataNode</strong>. -DataNode is a descriptor of a single database your application -will connect to. Cayenne mapping project can use more than one database, but for now, -we’ll only use one. With "project" selected on the left, click on <code>Create DataNode</code> button <span class="image"><img src="images/icon-node.png" alt="icon node"></span> -on the toolbar (or select <code>Project > Create DataNode</code> from the menu).</p> -</div> -<div class="paragraph"> -<p>A new DataNode is displayed. Now you need to specify JDBC connection parameters. For -an in-memory Derby database you can enter the following settings:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>JDBC Driver: org.apache.derby.jdbc.EmbeddedDriver</p> -</li> -<li> -<p>DB URL: jdbc:derby:memory:testdb;create=true</p> -</li> -</ul> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -We are creating an in-memory database here. So when - you stop your application, all the data will be lost. In most real-life - cases you’ll be connecting to a database that actually persists its data on - disk, but an in-memory DB will do for the simple tutorial. -</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Also you will need to change "Schema Update Strategy". Select -<code>org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy</code> from the dropdown, so that -Cayenne creates a new schema on Derby based on the ORM mapping when the application -starts.</p> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/base-datanode.png" alt="base datanode"> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="create-a-datamap"><a class="anchor" href="#create-a-datamap"></a>Create a DataMap</h4> -<div class="paragraph"> -<p>Now you will create a <strong>DataMap</strong>. DataMap is an object -that holds all the mapping information. To create it, click on "Create DataMap" button -<span class="image"><img src="images/icon-datamap.png" alt="icon datamap"></span> (or select a corresponding menu item). -Note that the newly created DataMap is automatically linked to the DataNode that you created in -the previous step. If there is more than one DataNode, you may need to link a DataMap -to the correct node manually. In other words a DataMap within DataDomain must point -to a database described by the map.</p> -</div> -<div class="paragraph"> -<p>You can leave all the DataMap defaults unchanged except for one - "Java Package". -Enter <code>org.example.cayenne.persistent</code>. This name will later be used for all persistent -classes.</p> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/base-datamap.png" alt="base datamap"> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="save-the-project"><a class="anchor" href="#save-the-project"></a>Save the Project</h4> -<div class="imageblock" style="float: right"> -<div class="content"> -<img src="images/idea-xmlfiles.png" alt="idea xmlfiles"> -</div> -</div> -<div class="paragraph"> -<p>Before you proceed with the actual mapping, let’s save the project. Click on "Save" -button in the toolbar and navigate to the <code>tutorial</code> IDEA project folder that was -created earlier in this section and its <code>src/main/resources</code> subfolder and save the -project there. Now go back to IDEA and you will see two Cayenne XML files.</p> -</div> -<div class="paragraph"> -<p>Note that the location of the XML files is not coincidental. Cayenne runtime looks for -<code>cayenne-*.xml</code> file in the application <code>CLASSPATH</code> and <code>src/main/resources</code> folder should -already be a "class folder" in IDEA for our project (and is also a standard location -that Maven would copy to a jar file, if we were using Maven from command-line).</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="getting-started-with-object-relational-mapping-orm"><a class="anchor" href="#getting-started-with-object-relational-mapping-orm"></a>2.2. Getting started with Object Relational Mapping (ORM)</h3> -<div class="paragraph"> -<p>The goal of this section is to learn how to create a simple Object-Relational model with -CayenneModeler. We will create a complete ORM model for the following database -schema:</p> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/cayenne-tutorial-model.png" alt="cayenne tutorial model"> -</div> -</div> -<div class="admonitionblock note"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-note" title="Note"></i> -</td> -<td class="content"> -Very often you’d have an existing database already, and - it can be quickly imported in Cayenne via "Tools > Reengineer Database - Schema". This will save you lots of time compared to manual mapping. However - understanding how to create the mapping by hand is important, so we are showing - the "manual" approach below. -</td> -</tr> -</table> -</div> -<div class="sect3"> -<h4 id="mapping-database-tables-and-columns"><a class="anchor" href="#mapping-database-tables-and-columns"></a>Mapping Database Tables and Columns</h4> -<div class="paragraph"> -<p>Lets go back to CayenneModeler where we have the newly created project open and start -by adding the ARTIST table. Database tables are called <strong>DbEntities</strong> -in Cayenne mapping (those can be actual tables or database views).</p> -</div> -<div class="paragraph"> -<p>Select "datamap" on the left-hand side project tree and click "Create DbEntity" button <span class="image"><img src="images/icon-dbentity.png" alt="icon dbentity"></span> -(or use "Project > Create DbEntity" menu). A new DbEntity is created. In "DbEntity -Name" field enter "ARTIST". Then click on "Create Attribute" button <span class="image"><img src="images/icon-attribute.png" alt="icon attribute"></span> -on the entity toolbar. This action changes the view to the "Attribute" -tab and adds a new attribute (attribute means a "table column" in this case) called -"untitledAttr". Let’s rename it to ID, make it an <code>INTEGER</code> and make it a PK:</p> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/modeler-artistid.png" alt="modeler artistid"> -</div> -</div> -<div class="paragraph"> -<p>Similarly add NAME <code>VARCHAR(200)</code> and DATE_OF_BIRTH <code>DATE</code> attributes. After that repeat -this procedure for PAINTING and GALLERY entities to match DB schema shown above.</p> -</div> -</div> -<div class="sect3"> -<h4 id="mapping-database-relationships"><a class="anchor" href="#mapping-database-relationships"></a>Mapping Database Relationships</h4> -<div class="paragraph"> -<p>Now we need to specify relationships between ARTIST, PAINTING and GALLERY tables. -Start by creating a one-to-many ARTIST/PAINTING relationship:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Select the ARTIST DbEntity on the left and click on the "Properties" tab.</p> -</li> -<li> -<p>Click on "Create Relationship" button on the entity toolbar <span class="image"><img src="images/icon-relationship.png" alt="icon relationship"></span> - a relationship -called "untitledRel" is created.</p> -</li> -<li> -<p>Choose the "Target" to be "Painting".</p> -</li> -<li> -<p>Click on the "Database Mapping" button <span class="image"><img src="images/icon-edit.png" alt="icon edit"></span> - relationship -configuration dialog is presented. Here you can assign a name to the -relationship and also its complimentary reverse relationship. This name can be -anything (this is really a symbolic name of the database referential -constraint), but it is recommended to use a valid Java identifier, as this will -save some typing later. We’ll call the relationship "paintings" and reverse -relationship "artist".</p> -</li> -<li> -<p>Click on "Add" button on the right to add a join</p> -</li> -<li> -<p>Select "ID" column for the "Source" and "ARTIST_ID" column for the target.</p> -</li> -<li> -<p>Relationship information should now look like this:</p> -</li> -</ul> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/modeler-dbrelationship.png" alt="modeler dbrelationship"> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>Click "Done" to confirm the changes and close the dialog.</p> -</li> -<li> -<p>Two complimentary relationships have been created - from ARTIST to PAINTING -and back. Still you may have noticed one thing is missing - "paintings" -relationship should be to-many, but "To Many" checkbox is not checked. Let’s -change that - check the checkbox for "paintings" relationship, and then click on -PAINTING DbEntity, and uncheck "artist" relationship "To Many" to make the -reverse relationship "to-one" as it should be.</p> -</li> -<li> -<p>Repeat the steps above to create a many-to-one relationship from PAINTING to GALLERY, calling the relationships pair -"gallery" and "paintings".</p> -</li> -</ul> -</div> -</div> -<div class="sect3"> -<h4 id="mapping-java-classes"><a class="anchor" href="#mapping-java-classes"></a>Mapping Java Classes</h4> -<div class="paragraph"> -<p>Now that the database schema mapping is complete, CayenneModeler can create mappings -of Java classes (aka "ObjEntities") by deriving everything from DbEntities. At present -there is no way to do it for the entire DataMap in one click, so we’ll do it for each -table individually.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Select "ARTIST" DbEntity and click on "Create ObjEntity" button <span class="image"><img src="images/icon-new_objentity.png" alt="icon new objentity"></span> -either on the entity toolbar or on the main toolbar. An ObjEntity called -"Artist" is created with a Java class field set to -"org.example.cayenne.persistent.Artist". The modeler transformed the database -names to the Java-friendly names (e.g., if you click on the "Attributes" tab, -you’ll see that "DATE_OF_BIRTH" column was converted to "dateOfBirth" Java class -attribute).</p> -</li> -<li> -<p>Select "GALLERY" DbEntity and click on "Create ObjEntity" button again - you’ll see a "Gallery" ObjEntity created.</p> -</li> -<li> -<p>Finally, do the same thing for "PAINTING".</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Now you need to synchronize relationships. Artist and Gallery entities were created -when there was no related "Painting" entity, so their relationships were not set.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Click on the "Artist" ObjEntity. Now click on "Sync ObjEntity with DbEntity" button on -the toolbar <span class="image"><img src="images/icon-sync.png" alt="icon sync"></span> - you will see the "paintings" relationship appear.</p> -</li> -<li> -<p>Do the same for the "Gallery" entity.</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Unless you want to customize the Java class and property names (which you can do easily) the mapping is complete.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="creating-java-classes"><a class="anchor" href="#creating-java-classes"></a>2.3. Creating Java Classes</h3> -<div class="paragraph"> -<p>Here we’ll generate the Java classes from the model that was created in the previous -section. CayenneModeler can be used to also generate the database schema, but since we -specified “CreateIfNoSchemaStrategy” earlier when we created a DataNode, we’ll skip the -database schema step. Still be aware that you can do it if you need to via "Tools > -Create Database Schema".</p> -</div> -<div class="sect3"> -<h4 id="creating-java-classes-2"><a class="anchor" href="#creating-java-classes-2"></a>Creating Java Classes</h4> -<div class="ulist"> -<ul> -<li> -<p>Select "Tools > Generate Classes" menu.</p> -</li> -<li> -<p>For "Type" select "Standard Persistent Objects", if it is not already selected.</p> -</li> -<li> -<p>For the "Output Directory" select “src/main/java” folder under your IDEA -project folder (this is a "peer" location to the <code>cayenne-*.xml</code> location we -selected before).</p> -</li> -<li> -<p>Click on "Classes" tab and check the "Check All Classes" checkbox -(unless it is already checked and reads "Uncheck all Classes").</p> -</li> -<li> -<p>Click "Generate"</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Now go back to IDEA - you -should see pairs of classes generated for each mapped entity. You probably also see that -there’s a bunch of red squiggles next to the newly generated Java classes in IDEA. -This is because our project does not include Cayenne as a Maven dependency yet. Let’s -fix it now by adding "cayenne-server" and "cayenne-java8" artifacts in the bottom of the <code>pom.xml</code> file. -Also we should tell Maven compile plugin that our project needs Java 8. -The resulting POM should look like this:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><project</span> <span class="attribute-name">xmlns</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://maven.apache.org/POM/4.0.0</span><span class="delimiter">"</span></span> <span class="attribute-name">xmlns:xsi</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://www.w3.org/2001/XMLSchema-instance</span><span class="delimiter">"</span></span> - <span class="attribute-name">xsi:schemaLocation</span>=<span class="string"><span class="delimiter">"</span><span class="content">http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd</span><span class="delimiter">"</span></span><span class="tag">></span> - <span class="tag"><modelVersion></span>4.0.0<span class="tag"></modelVersion></span> - <span class="tag"><groupId></span>org.example.cayenne<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>tutorial<span class="tag"></artifactId></span> - <span class="tag"><version></span>0.0.1-SNAPSHOT<span class="tag"></version></span> - <span class="tag"><cayenne.version></span>4.1.M2-SNAPSHOT<span class="tag"></version></span> <i class="conum" data-value="1"></i><b>(1)</b> - - <span class="tag"><dependencies></span> - <span class="tag"><dependency></span> - <span class="tag"><groupId></span>org.apache.cayenne<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>cayenne-server<span class="tag"></artifactId></span> - <span class="tag"><version></span>${cayenne.version}<span class="tag"></version></span> - <span class="tag"></dependency></span> - <span class="comment"><!-- For java.time.* types you need to use this dependency--></span> - <span class="tag"><dependency></span> - <span class="tag"><groupId></span>org.apache.cayenne<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>cayenne-java8<span class="tag"></artifactId></span> - <span class="tag"><version></span>${cayenne.version}<span class="tag"></version></span> - <span class="tag"></dependency></span> - <span class="tag"><dependency></span> - <span class="tag"><groupId></span>org.slf4j<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>slf4j-simple<span class="tag"></artifactId></span> - <span class="tag"><version></span>1.7.25<span class="tag"></version></span> - <span class="tag"></dependency></span> - <span class="tag"></dependencies></span> - - <span class="tag"><build></span> - <span class="tag"><plugins></span> - <span class="comment"><!-- Tell maven to support Java 8 --></span> - <span class="tag"><plugin></span> - <span class="tag"><groupId></span>org.apache.maven.plugins<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>maven-compiler-plugin<span class="tag"></artifactId></span> - <span class="tag"><version></span>3.6.1<span class="tag"></version></span> - <span class="tag"><configuration></span> - <span class="tag"><source></span>1.8<span class="tag"></source></span> - <span class="tag"><target></span>1.8<span class="tag"></target></span> - <span class="tag"></configuration></span> - <span class="tag"></plugin></span> - <span class="tag"></plugins></span> - <span class="tag"></build></span> -<span class="tag"></project></span></code></pre> -</div> -</div> -<div class="colist arabic"> -<table> -<tr> -<td><i class="conum" data-value="1"></i><b>1</b></td> -<td>Here you can specify the version of Cayenne you are actually using</td> -</tr> -</table> -</div> -<div class="paragraph"> -<p>Your computer must be connected to the internet. Once you edit the <code>pom.xml</code>, IDEA -will download the needed Cayenne jar file and add it to the project build path. As a -result, all the errors should disappear. In tutorial for console output we use slf4j-simple logger -implementation. Due to use SLF4J logger in Apache Cayenne, you can use your custom logger (e.g. log4j -or commons-logging) through bridges.</p> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/idea-generated-classes.png" alt="idea generated classes"> -</div> -</div> -<div class="paragraph"> -<p>Now let’s check the entity class pairs. Each one is made of a superclass (e.g. <code>_Artist</code>) -and a subclass (e.g. <code>Artist</code>). You <strong>should not</strong> modify the -superclasses whose names start with "_" (underscore), as they will be replaced on -subsequent generator runs. Instead all custom logic should be placed in the subclasses -in <code>org.example.cayenne.persistent</code> package - those will never be overwritten by the -class generator.</p> -</div> -<div class="admonitionblock tip"> -<table> -<tr> -<td class="icon"> -<i class="fa icon-tip" title="Tip"></i> -</td> -<td class="content"> -<div class="title">Class Generation Hint</div> -<div class="paragraph"> -<p>Often you’d start by generating classes from the -Modeler, but at the later stages of the project the generation is usually -automated either via Ant cgen task or Maven cgen mojo. All three methods are -interchangeable, however Ant and Maven methods would ensure that you never -forget to regenerate classes on mapping changes, as they are integrated into -the build cycle.</p> -</div> -</td> -</tr> -</table> -</div> -</div> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="learning-cayenne-api"><a class="anchor" href="#learning-cayenne-api"></a>3. Learning Cayenne API</h2> -<div class="sectionbody"> -<div class="sect2"> -<h3 id="getting-started-with-objectcontext"><a class="anchor" href="#getting-started-with-objectcontext"></a>3.1. Getting started with ObjectContext</h3> -<div class="paragraph"> -<p>In this section we’ll write a simple main class to run our application, and get a brief -introduction to Cayenne ObjectContext.</p> -</div> -<div class="sect3"> -<h4 id="creating-the-main-class"><a class="anchor" href="#creating-the-main-class"></a>Creating the Main Class</h4> -<div class="ulist"> -<ul> -<li> -<p>In IDEA create a new class called “Main” in the “org.example.cayenne” package.</p> -</li> -<li> -<p>Create a standard "main" method to make it a runnable class:</p> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">package</span> <span class="namespace">org.example.cayenne</span>; - -<span class="directive">public</span> <span class="type">class</span> <span class="class">Main</span> { - - <span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span><span class="type">[]</span> args) { - } -}</code></pre> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>The first thing you need to be able to access the database is to create a -<code>ServerRuntime</code> object (which is essentially a wrapper around Cayenne stack) and -use it to obtain an instance of an -<code>ObjectContext</code>.</p> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">package</span> <span class="namespace">org.example.cayenne</span>; - -<span class="keyword">import</span> <span class="include">org.apache.cayenne.ObjectContext</span>; -<span class="keyword">import</span> <span class="include">org.apache.cayenne.configuration.server.ServerRuntime</span>; - -<span class="directive">public</span> <span class="type">class</span> <span class="class">Main</span> { - - <span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span><span class="type">[]</span> args) { - ServerRuntime cayenneRuntime = ServerRuntime.builder() - .addConfig(<span class="string"><span class="delimiter">"</span><span class="content">cayenne-project.xml</span><span class="delimiter">"</span></span>) - .build(); - ObjectContext context = cayenneRuntime.newContext(); - } -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p><code>ObjectContext</code> is an isolated "session" in Cayenne that provides all needed API -to work with data. ObjectContext has methods to execute queries and manage -persistent objects. We’ll discuss them in the following sections. When the first -ObjectContext is created in the application, Cayenne loads XML mapping files and -creates a shared access stack that is later reused by other ObjectContexts.</p> -</div> -</div> -<div class="sect3"> -<h4 id="running-application"><a class="anchor" href="#running-application"></a>Running Application</h4> -<div class="paragraph"> -<p>Let’s check what happens when you run the application. But before we do that we need -to add another dependency to the <code>pom.xml</code> - Apache Derby, our embedded database engine. -The following piece of XML needs to be added to the -<code><dependencies>…​</dependencies></code> section, where we already have Cayenne -jars:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><dependency></span> - <span class="tag"><groupId></span>org.apache.derby<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>derby<span class="tag"></artifactId></span> - <span class="tag"><version></span>10.13.1.1<span class="tag"></version></span> -<span class="tag"></dependency></span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>Now we are ready to run. Right click the "Main" class in IDEA and select "Run 'Main.main()'".</p> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/idea-file-run-menu.png" alt="idea file run menu"> -</div> -</div> -<div class="paragraph"> -<p>In the console you’ll see output similar to this, indicating that Cayenne stack has been started:</p> -</div> -<div class="literalblock"> -<div class="content"> -<pre>INFO: Loading XML configuration resource from file:/.../cayenne-project.xml -INFO: Loading XML DataMap resource from file:/.../datamap.map.xml -INFO: loading user name and password. -INFO: Connecting to 'jdbc:derby:memory:testdb;create=true' as 'null' -INFO: +++ Connecting: SUCCESS. -INFO: setting DataNode 'datanode' as default, used by all unlinked DataMaps</screen></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="how-to-configure-cayenne-logging"><a class="anchor" href="#how-to-configure-cayenne-logging"></a>How to Configure Cayenne Logging</h4> -<div class="paragraph"> -<p>Follow the instructions in the logging chapter to tweak verbosity of the logging output.</p> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="getting-started-with-persistent-objects"><a class="anchor" href="#getting-started-with-persistent-objects"></a>3.2. Getting started with persistent objects</h3> -<div class="paragraph"> -<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> -<div class="sect3"> -<h4 id="inspecting-and-customizing-persistent-objects"><a class="anchor" href="#inspecting-and-customizing-persistent-objects"></a>Inspecting and Customizing Persistent Objects</h4> -<div class="paragraph"> -<p>Persistent classes in Cayenne implement a DataObject interface. If you inspect any of -the classes generated earlier in this tutorial (e.g. -<code>org.example.cayenne.persistent.Artist</code>), you’ll see that it extends a class with the name -that starts with underscore (<code>org.example.cayenne.persistent.auto._Artist</code>), which in turn -extends from <code>org.apache.cayenne.CayenneDataObject</code>. Splitting each persistent class into -user-customizable subclass (<code>Xyz</code>) and a generated superclass (<code>_Xyz</code>) is a useful technique -to avoid overwriting the custom code when refreshing classes from the mapping -model.</p> -</div> -<div class="paragraph"> -<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> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">Artist</span> <span class="directive">extends</span> _Artist { - - <span class="directive">static</span> <span class="directive">final</span> <span class="predefined-type">String</span> DEFAULT_DATE_FORMAT = <span class="string"><span class="delimiter">"</span><span class="content">yyyyMMdd</span><span class="delimiter">"</span></span>; - - <span class="comment">/** - * Sets date of birth using a string in format yyyyMMdd. - */</span> - <span class="directive">public</span> <span class="type">void</span> setDateOfBirthString(<span class="predefined-type">String</span> yearMonthDay) { - <span class="keyword">if</span> (yearMonthDay == <span class="predefined-constant">null</span>) { - setDateOfBirth(<span class="predefined-constant">null</span>); - <span class="keyword">return</span>; - } - - LocalDate date; - <span class="keyword">try</span> { - DateTimeFormatter formatter = DateTimeFormatter - .ofPattern(DEFAULT_DATE_FORMAT); - date = LocalDate.parse(yearMonthDay, formatter); - } <span class="keyword">catch</span> (DateTimeParseException e) { - <span class="keyword">throw</span> <span class="keyword">new</span> <span class="exception">IllegalArgumentException</span>( - <span class="string"><span class="delimiter">"</span><span class="content">A date argument must be in format '</span><span class="delimiter">"</span></span> - + DEFAULT_DATE_FORMAT + <span class="string"><span class="delimiter">"</span><span class="content">': </span><span class="delimiter">"</span></span> + yearMonthDay); - } - setDateOfBirth(date); - } -}</code></pre> -</div> -</div> -</div> -<div class="sect3"> -<h4 id="create-new-objects"><a class="anchor" href="#create-new-objects"></a>Create New Objects</h4> -<div class="paragraph"> -<p>Now we’ll create a bunch of objects and save them to the database. An object is -created and registered with <code>ObjectContext</code> using “newObject” method. Objects <strong>must</strong> be registered -with <code>DataContext</code> to be persisted and to allow setting relationships with other objects. -Add this code to the "main" method of the Main class:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java">Artist picasso = context.newObject(Artist.class); -picasso.setName(<span class="string"><span class="delimiter">"</span><span class="content">Pablo Picasso</span><span class="delimiter">"</span></span>); -picasso.setDateOfBirthString(<span class="string"><span class="delimiter">"</span><span class="content">18811025</span><span class="delimiter">"</span></span>);</code></pre> -</div> -</div> -<div class="paragraph"> -<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> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java">Gallery metropolitan = context.newObject(Gallery.class); -metropolitan.setName(<span class="string"><span class="delimiter">"</span><span class="content">Metropolitan Museum of Art</span><span class="delimiter">"</span></span>); -Painting girl = context.newObject(Painting.class); -girl.setName(<span class="string"><span class="delimiter">"</span><span class="content">Girl Reading at a Table</span><span class="delimiter">"</span></span>); -Painting stein = context.newObject(Painting.class); -stein.setName(<span class="string"><span class="delimiter">"</span><span class="content">Gertrude Stein</span><span class="delimiter">"</span></span>);</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Now we can link the objects together, establishing relationships. Note that in each -case below relationships are automatically established in both directions (e.g. -<code>picasso.addToPaintings(girl)</code> has exactly the same effect as -<code>girl.setToArtist(picasso)</code>).</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java">picasso.addToPaintings(girl); -picasso.addToPaintings(stein); -girl.setGallery(metropolitan); -stein.setGallery(metropolitan);</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Now lets save all five new objects, in a single method call:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java">context.commitChanges();</code></pre> -</div> -</div> -<div class="paragraph"> -<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> -</div> -<div class="literalblock"> -<div class="content"> -<pre>... -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> -</div> -</div> -<div class="paragraph"> -<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> -<div class="sect2"> -<h3 id="selecting-objects"><a class="anchor" href="#selecting-objects"></a>3.3. Selecting Objects</h3> -<div class="paragraph"> -<p>This chapter shows how to select objects from the database using <code>ObjectSelect</code> query.</p> -</div> -<div class="sect3"> -<h4 id="introducing-objectselect"><a class="anchor" href="#introducing-objectselect"></a>Introducing ObjectSelect</h4> -<div class="paragraph"> -<p>It was shown before how to persist new objects. Cayenne queries are used to access -already saved objects. The primary query type used for selecting objects is <code>ObjectSelect</code>. -It can be mapped in CayenneModeler or created -via the API. We’ll use the latter approach in this section. We don’t have too much data -in the database yet, but we can still demonstrate the main principles below.</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Select all paintings (the code, and the log output it generates):</p> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="predefined-type">List</span><Painting> paintings1 = ObjectSelect.query(Painting.class).select(context);</code></pre> -</div> -</div> -<div class="literalblock"> -<div class="content"> -<pre>INFO: SELECT t0.GALLERY_ID, t0.ARTIST_ID, t0.NAME, t0.ID FROM PAINTING t0 -INFO: === returned 2 rows. - took 18 ms.</pre> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>Select paintings that start with “gi”, ignoring case:</p> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="predefined-type">List</span><Painting> paintings2 = ObjectSelect.query(Painting.class) - .where(Painting.NAME.likeIgnoreCase(<span class="string"><span class="delimiter">"</span><span class="content">gi%</span><span class="delimiter">"</span></span>)).select(context);</code></pre> -</div> -</div> -<div class="literalblock"> -<div class="content"> -<pre>INFO: SELECT t0.GALLERY_ID, t0.NAME, t0.ARTIST_ID, t0.ID FROM PAINTING t0 WHERE UPPER(t0.NAME) LIKE UPPER(?) - [bind: 1->NAME:'gi%'] - prepared in 6 ms. -INFO: === returned 1 row. - took 18 ms.</pre> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>Select all paintings done by artists who were born more than a 100 years ago:</p> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="predefined-type">List</span><Painting> paintings3 = ObjectSelect.query(Painting.class) - .where(Painting.ARTIST.dot(Artist.DATE_OF_BIRTH).lt(LocalDate.of(<span class="integer">1900</span>,<span class="integer">1</span>,<span class="integer">1</span>))) - .select(context);</code></pre> -</div> -</div> -<div class="literalblock"> -<div class="content"> -<pre>INFO: SELECT t0.GALLERY_ID, t0.NAME, t0.ARTIST_ID, t0.ID FROM PAINTING t0 JOIN ARTIST t1 ON (t0.ARTIST_ID = t1.ID) - WHERE t1.DATE_OF_BIRTH < ? [bind: 1->DATE_OF_BIRTH:'1911-01-01 00:00:00.493'] - prepared in 7 ms. -INFO: === returned 2 rows. - took 25 ms.</pre> -</div> -</div> -</div> -</div> -<div class="sect2"> -<h3 id="deleting-objects"><a class="anchor" href="#deleting-objects"></a>3.4. Deleting Objects</h3> -<div class="paragraph"> -<p>This chapter explains how to model relationship delete rules and how to delete individual -objects as well as sets of objects. Also demonstrated the use of Cayenne class to run a -query.</p> -</div> -<div class="sect3"> -<h4 id="setting-up-delete-rules"><a class="anchor" href="#setting-up-delete-rules"></a>Setting Up Delete Rules</h4> -<div class="paragraph"> -<p>Before we discuss the API for object deletion, lets go back to CayenneModeler and set -up some delete rules. Doing this is optional but will simplify correct handling of the -objects related to deleted objects. -In the Modeler go to "Artist" ObjEntity, "Relationships" tab and select "Cascade" for -the "paintings" relationship delete rule:</p> -</div> -<div class="imageblock"> -<div class="content"> -<img src="images/modeler-deleterule.png" alt="modeler deleterule"> -</div> -</div> -<div class="paragraph"> -<p>Repeat this step for other relationships:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>For Gallery set "paintings" relationship to be "Nullify", as a painting can exist without being displayed in a gallery.</p> -</li> -<li> -<p>For Painting set both relationships rules to "Nullify".</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>Now save the mapping.</p> -</div> -</div> -<div class="sect3"> -<h4 id="deleting-objects-2"><a class="anchor" href="#deleting-objects-2"></a>Deleting Objects</h4> -<div class="paragraph"> -<p>While deleting objects is possible via SQL, qualifying a delete on one or more IDs, a -more common way in Cayenne (or ORM in general) is to get a hold of the object first, and -then delete it via the context. Let’s use utility class Cayenne to find an -artist:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java">Artist picasso = ObjectSelect.query(Artist.class) - .where(Artist.NAME.eq(<span class="string"><span class="delimiter">"</span><span class="content">Pablo Picasso</span><span class="delimiter">"</span></span>)).selectOne(context);</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Now let’s delete the artist:</p> -</div> -<div class="listingblock"> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">if</span> (picasso != <span class="predefined-constant">null</span>) { - context.deleteObject(picasso); - context.commitChanges(); -}</code></pre> -</div> -</div> -<div class="paragraph"> -<p>Since we set up "Cascade" delete rule for the Artist.paintings relationships, Cayenne -will automatically delete all paintings of this artist. So when your run the app you’ll -see this output:</p> -</div> -<div class="literalblock"> -<div class="content"> -<pre>INFO: SELECT t0.DATE_OF_BIRTH, t0.NAME, t0.ID FROM ARTIST t0 - WHERE t0.NAME = ? [bind: 1->NAME:'Pablo Picasso'] - prepared in 6 ms. -INFO: === returned 1 row. - took 18 ms. -INFO: +++ transaction committed. -INFO: --- transaction started. -INFO: DELETE FROM PAINTING WHERE ID = ? -INFO: [batch bind: 1->ID:200] -INFO: [batch bind: 1->ID:201] -INFO: === updated 2 rows. -INFO: DELETE FROM ARTIST WHERE ID = ? -INFO: [batch bind: 1->ID:200] -INFO: === updated 1 row. -INFO: +++ transaction committed.</pre> -</div> -</div> -</div> -</div> -</div> -</div> -<div class="sect1"> -<h2 id="converting-to-web-application"><a class="anchor" href="#converting-to-web-application"></a>4. Converting to Web Application</h2> -<div class="sectionbody"> -<div class="paragraph"> -<p>This chapter shows how to work with Cayenne in a web application.</p> -</div> -<div class="sect2"> -<h3 id="converting-tutorial-to-a-web-application"><a class="anchor" href="#converting-tutorial-to-a-web-application"></a>4.1. Converting Tutorial to a Web Application</h3> -<div class="paragraph"> -<p>The web part of the web application tutorial is done in JSP, which is the least common -denominator of the Java web technologies, and is intentionally simplistic from the UI -perspective, to concentrate on Cayenne integration aspect, rather than the interface. A -typical Cayenne web application works like this:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Cayenne configuration is loaded when an application context is started, using a special servlet filter.</p> -</li> -<li> -<p>User requests are intercepted by the filter, and the DataContext is bound to -the request thread, so the application can access it easily from anywhere.</p> -</li> -<li> -<p>The same DataContext instance is reused within a single user session; -different sessions use different DataContexts (and therefore different sets of -objects). <em>The context can be scoped differently -depending on the app specifics. For the tutorial we’ll be using a -session-scoped context.</em></p> -</li> -</ul> -</div> -<div class="paragraph"> -<p>So let’s convert the tutorial that we created to a web application:</p> -</div> -<div class="ulist"> -<ul> -<li> -<p>In IDEA under "tutorial" project folder create a new folder <code>src/main/webapp/WEB-INF</code>.</p> -</li> -<li> -<p>Under <code>WEB-INF</code> create a new file <code>web.xml</code> (a standard web app descriptor):</p> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="title">web.xml</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor"><?xml version="1.0" encoding="utf-8"?></span> -<span class="doctype"><!DOCTYPE web-app - PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" - "http://java.sun.com/dtd/web-app_2_3.dtd"></span> -<span class="tag"><web-app></span> - <span class="tag"><display-name></span>Cayenne Tutorial<span class="tag"></display-name></span> - - <span class="comment"><!-- This filter bootstraps ServerRuntime and then provides each request thread - with a session-bound DataContext. Note that the name of the filter is important, - as it points it to the right named configuration file. - --></span> - <span class="tag"><filter></span> - <span class="tag"><filter-name></span>cayenne-project<span class="tag"></filter-name></span> - <span class="tag"><filter-class></span>org.apache.cayenne.configuration.web.CayenneFilter<span class="tag"></filter-class></span> - <span class="tag"></filter></span> - <span class="tag"><filter-mapping></span> - <span class="tag"><filter-name></span>cayenne-project<span class="tag"></filter-name></span> - <span class="tag"><url-pattern></span>/*<span class="tag"></url-pattern></span> - <span class="tag"></filter-mapping></span> - <span class="tag"><welcome-file-list></span> - <span class="tag"><welcome-file></span>index.jsp<span class="tag"></welcome-file></span> - <span class="tag"></welcome-file-list></span> -<span class="tag"></web-app></span></code></pre> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>Create the artist browser page <code>src/main/webapp/index.jsp</code> file with the following contents:</p> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="title">webapp/index.jsp</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="jsp"><%@ page language="java" contentType="text/html" %> -<%@ page import="org.example.cayenne.persistent.*" %> -<%@ page import="org.apache.cayenne.*" %> -<%@ page import="org.apache.cayenne.query.*" %> -<%@ page import="org.apache.cayenne.exp.*" %> -<%@ page import="java.util.*" %> - -<% - ObjectContext context = BaseContext.getThreadObjectContext(); - List<Artist> artists = ObjectSelect.query(Artist.class) - .orderBy(Artist.NAME.asc()) - .select(context); -%> - -<html> - <head> - <title>Main</title> - </head> - <body> - <h2>Artists:</h2> - - <% if(artists.isEmpty()) {%> - <p>No artists found</p> - <% } else { - for(Artist a : artists) { - %> - <p><a href="detail.jsp?id=<%=Cayenne.intPKForObject(a)%>"> <%=a.getName()%> </a></p> - <% - } - } %> - <hr> - <p><a href="detail.jsp">Create new artist...</a></p> - </body> -</html></code></pre> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>Create the artist editor page <code>src/main/webapp/detail.jsp</code> with the following content:</p> -</li> -</ul> -</div> -<div class="listingblock"> -<div class="title">webapp/detail.jsp</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="jsp"><%@ page language="java" contentType="text/html" %> -<%@ page import="org.example.cayenne.persistent.*" %> -<%@ page import="org.apache.cayenne.*" %> -<%@ page import="org.apache.cayenne.query.*" %> -<%@ page import="java.util.*" %> -<%@ page import="java.text.*" %> -<%@ page import="java.time.format.DateTimeFormatter" %> - -<% - ObjectContext context = BaseContext.getThreadObjectContext(); - String id = request.getParameter("id"); - - // find artist for id - Artist artist = null; - if(id != null &amp;&amp; id.trim().length() > 0) { - artist = SelectById.query(Artist.class, Integer.parseInt(id)).selectOne(context); - } - - if("POST".equals(request.getMethod())) { - // if no id is saved in the hidden field, we are dealing with - // create new artist request - if(artist == null) { - artist = context.newObject(Artist.class); - } - - // note that in a real application we would so dome validation ... - // here we just hope the input is correct - artist.setName(request.getParameter("name")); - artist.setDateOfBirthString(request.getParameter("dateOfBirth")); - - context.commitChanges(); - - response.sendRedirect("index.jsp"); - } - - if(artist == null) { - // create transient artist for the form response rendering - artist = new Artist(); - } - - String name = artist.getName() == null ? "" : artist.getName(); - - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); - String dob = artist.getDateOfBirth() == null - ? "" :artist.getDateOfBirth().format(formatter); -%> -<html> - <head> - <title>Artist Details</title> - </head> - <body> - <h2>Artists Details</h2> - <form name="EditArtist" action="detail.jsp" method="POST"> - <input type="hidden" name="id" value="<%= id != null ? id : "" %>" /> - <table border="0"> - <tr> - <td>Name:</td> - <td><input type="text" name="name" value="<%= name %>"/></td> - </tr> - <tr> - <td>Date of Birth (yyyyMMdd):</td> - <td><input type="text" name="dateOfBirth" value="<%= dob %>"/></td> - </tr> - <tr> - <td></td> - <td align="right"><input type="submit" value="Save" /></td> - </tr> - </table> - </form> - </body> -</html></code></pre> -</div> -</div> -<div class="sect3"> -<h4 id="running-web-application"><a class="anchor" href="#running-web-application"></a>Running Web Application</h4> -<div class="paragraph"> -<p>We need to provide javax servlet-api for our application.</p> -</div> -<div class="listingblock"> -<div class="title">pom.xml</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><dependency></span> - <span class="tag"><groupId></span>javax.servlet<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>javax.servlet-api<span class="tag"></artifactId></span> - <span class="tag"><version></span>3.1.0<span class="tag"></version></span> - <span class="tag"><scope></span>provided<span class="tag"></scope></span> -<span class="tag"></dependency></span></code></pre> -</div> -</div> -<div class="paragraph"> -<p>Also to run the web application we’ll use "maven-jetty-plugin". To activate it, -let’s add the following piece of code to the <code>pom.xml</code> file, following the "dependencies" -section and save the POM:</p> -</div> -<div class="listingblock"> -<div class="title">pom.xml</div> -<div class="content"> -<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><build></span> - <span class="tag"><plugins></span> - <span class="tag"><plugin></span> - <span class="tag"><groupId></span>org.eclipse.jetty<span class="tag"></groupId></span> - <span class="tag"><artifactId></span>jetty-maven-plugin<span class="tag"></artifactId></span> - <span class="tag"><version></span>9.3.14.v20161028<span class="tag"></version></span> - <span class="tag"></plugin></span> - <span class="tag"></plugins></span> -<span class="tag"></build></span></code></pre> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>Go to "Select Run/Debug Configuration" menu, and then "Edit Configuration…​"</p> -</li> -</ul> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/idea-edit-configurations.png" alt="idea edit configurations"> -</div> -</div> -<div class="ulist"> -<ul> -<li> -<p>Click <code>+</code> button and select "Maven". Enter "Name" and "Command line" as shown on screenshot:</p> -</li> -</ul> -</div> -<div class="paragraph"> -<p><span class="image"><img src="images/idea-run-configuration.png" alt="idea run configuration"></span></p> -</div> -<div class="ulist"> -<ul> -<li> -<p>Click "Apply" and "Run". On the first execution it may take a few minutes for -Jetty plugin to download all dependencies, but eventually you’ll see the logs -like this:</p> -<div class="literalblock"> -<div class="content"> -<pre>[INFO] ------------------------------------------------------------------------ -[INFO] Building tutorial 0.0.1-SNAPSHOT -[INFO] ------------------------------------------------------------------------ -... -[INFO] Configuring Jetty for project: tutorial -[INFO] webAppSourceDirectory not set. Trying src/main/webapp -[INFO] Reload Mechanic: automatic -[INFO] Classes = /.../tutorial/target/classes -[INFO] Logging initialized @1617ms -[INFO] Context path = / -[INFO] Tmp directory = /.../tutorial/target/tmp -[INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml -[INFO] Web overrides = none -[INFO] web.xml file = file:/.../tutorial/src/main/webapp/WEB-INF/web.xml -[INFO] Webapp directory = /.../tutorial/src/main/webapp -[INFO] jetty-9.3.0.v20150612 -[INFO] Started o.e.j.m.p.JettyWebAppContext@6872f9c8{/,file:/.../tutorial/src/main/webapp/,AVAILABLE}{file:/.../tutorial/src/main/webapp/} -[INFO] Started ServerConnector@723875bc{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} -[INFO] Started @2367ms -[INFO] Started Jetty Server</screen></pre> -</div> -</div> -</li> -<li> -<p>So the Jetty container just started.</p> -</li> -<li> -<p>Now go to <a href="http://localhost:8080/" class="bare">http://localhost:8080/</a> URL. You should see "No artists found message" in the web browser and -the following output in the IDEA console:</p> -<div class="literalblock"> -<div class="content"> -<pre>INFO: Loading XML configuration resource from file:/.../tutorial/target/classes/cayenne-project.xml -INFO: loading user name and password. -INFO: Connecting to 'jdbc:derby:memory:testdb;create=true' as 'null' -INFO: +++ Connecting: SUCCESS. -INFO: setting DataNode 'datanode' as default, used by all unlinked DataMaps -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: SELECT t0.DATE_OF_BIRTH, t0.NAME, t0.ID FROM ARTIST t0 ORDER BY t0.NAME -INFO: === returned 0 rows. - took 17 ms. -INFO: +++ transaction committed.</screen></pre> -</div> -</div> -</li> -<li> -<p>You can click on "Create new artist" link to create artists. Existing artists can be edited by clicking on their name:</p> -</li> -</ul> -</div> -<div class="imageblock" style="text-align: center"> -<div class="content"> -<img src="images/chrome-webapp.png" alt="chrome webapp"> -</div> -</div> -<div class="paragraph"> -<p>You are done with the tutorial!</p> -</div> -</div> -</div> -</div> -</div> \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/base-datamap.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/base-datamap.png b/src/main/site/content/docs/4.0/getting-started/images/base-datamap.png deleted file mode 100644 index a12bc01..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/base-datamap.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/base-datanode.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/base-datanode.png b/src/main/site/content/docs/4.0/getting-started/images/base-datanode.png deleted file mode 100644 index 69939bb..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/base-datanode.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/cayenne-tutorial-model.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/cayenne-tutorial-model.png b/src/main/site/content/docs/4.0/getting-started/images/cayenne-tutorial-model.png deleted file mode 100644 index 454d198..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/cayenne-tutorial-model.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/chrome-webapp.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/chrome-webapp.png b/src/main/site/content/docs/4.0/getting-started/images/chrome-webapp.png deleted file mode 100644 index 603e1df..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/chrome-webapp.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/database-schema.jpg ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/database-schema.jpg b/src/main/site/content/docs/4.0/getting-started/images/database-schema.jpg deleted file mode 100644 index 9d4ee21..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/database-schema.jpg and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/icon-attribute.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/icon-attribute.png b/src/main/site/content/docs/4.0/getting-started/images/icon-attribute.png deleted file mode 100644 index 77a68eb..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/icon-attribute.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/icon-datamap.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/icon-datamap.png b/src/main/site/content/docs/4.0/getting-started/images/icon-datamap.png deleted file mode 100644 index 2ea96ca..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/icon-datamap.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/icon-dbentity.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/icon-dbentity.png b/src/main/site/content/docs/4.0/getting-started/images/icon-dbentity.png deleted file mode 100644 index 87d9d8a..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/icon-dbentity.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/icon-edit.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/icon-edit.png b/src/main/site/content/docs/4.0/getting-started/images/icon-edit.png deleted file mode 100644 index 027c482..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/icon-edit.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/icon-new_objentity.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/icon-new_objentity.png b/src/main/site/content/docs/4.0/getting-started/images/icon-new_objentity.png deleted file mode 100644 index 8735d7a..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/icon-new_objentity.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/icon-node.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/icon-node.png b/src/main/site/content/docs/4.0/getting-started/images/icon-node.png deleted file mode 100644 index 2ff4383..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/icon-node.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/icon-relationship.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/icon-relationship.png b/src/main/site/content/docs/4.0/getting-started/images/icon-relationship.png deleted file mode 100644 index 44ed7eb..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/icon-relationship.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/icon-sync.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/icon-sync.png b/src/main/site/content/docs/4.0/getting-started/images/icon-sync.png deleted file mode 100644 index 03e8623..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/icon-sync.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/idea-edit-configurations.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/idea-edit-configurations.png b/src/main/site/content/docs/4.0/getting-started/images/idea-edit-configurations.png deleted file mode 100644 index df1d524..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/idea-edit-configurations.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/idea-file-run-menu.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/idea-file-run-menu.png b/src/main/site/content/docs/4.0/getting-started/images/idea-file-run-menu.png deleted file mode 100644 index 30cf05e..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/idea-file-run-menu.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/idea-generated-classes.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/idea-generated-classes.png b/src/main/site/content/docs/4.0/getting-started/images/idea-generated-classes.png deleted file mode 100644 index e69de29..0000000 http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/idea-run-configuration.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/idea-run-configuration.png b/src/main/site/content/docs/4.0/getting-started/images/idea-run-configuration.png deleted file mode 100644 index 3ebbb62..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/idea-run-configuration.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/idea-xmlfiles.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/idea-xmlfiles.png b/src/main/site/content/docs/4.0/getting-started/images/idea-xmlfiles.png deleted file mode 100644 index 1b4707d..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/idea-xmlfiles.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/modeler-artistid.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/modeler-artistid.png b/src/main/site/content/docs/4.0/getting-started/images/modeler-artistid.png deleted file mode 100644 index fb8c1dd..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/modeler-artistid.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/modeler-dbrelationship.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/modeler-dbrelationship.png b/src/main/site/content/docs/4.0/getting-started/images/modeler-dbrelationship.png deleted file mode 100644 index 4b23eb5..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/modeler-dbrelationship.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/modeler-deleterule.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/modeler-deleterule.png b/src/main/site/content/docs/4.0/getting-started/images/modeler-deleterule.png deleted file mode 100644 index 86ada13..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/modeler-deleterule.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/modeler-started.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/modeler-started.png b/src/main/site/content/docs/4.0/getting-started/images/modeler-started.png deleted file mode 100644 index dbf8324..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/modeler-started.png and /dev/null differ http://git-wip-us.apache.org/repos/asf/cayenne-website/blob/ecbc2ebc/src/main/site/content/docs/4.0/getting-started/images/tutorial-idea-project.png ---------------------------------------------------------------------- diff --git a/src/main/site/content/docs/4.0/getting-started/images/tutorial-idea-project.png b/src/main/site/content/docs/4.0/getting-started/images/tutorial-idea-project.png deleted file mode 100644 index 058dc1d..0000000 Binary files a/src/main/site/content/docs/4.0/getting-started/images/tutorial-idea-project.png and /dev/null differ