cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ntimof...@apache.org
Subject [10/11] cayenne git commit: CAY-2371 Switch documentation from Docbook to Asciidoctor format
Date Fri, 05 Jan 2018 14:21:38 GMT
http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
new file mode 100644
index 0000000..74b836a
--- /dev/null
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
@@ -0,0 +1,244 @@
+// 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.
+[[expressions]]
+=== Expressions
+
+==== Expressions Overview
+
+Cayenne provides a simple yet powerful object-based expression language. The most common use of expressions are to build qualifiers and orderings of queries that are later converted to SQL by Cayenne and to evaluate in-memory against specific objects (to access certain values in the object graph or to perform in-memory object filtering and sorting). Cayenne provides API to build expressions in the code and a parser to create expressions from strings.
+
+==== Path Expressions
+
+Before discussing how to build expressions, it is important to understand one group of expressions widely used in Cayenne - path expressions. There are two types of path expressions - object and database, used for navigating graphs of connected objects or joined DB tables respectively. Object paths are much more commonly used, as after all Cayenne is supposed to provide a degree of isolation of the object model from the database. However database paths are helpful in certain situations. General structure of path expressions is the following:
+
+----
+ [db:]segment[+][.segment[+]...]
+----
+
+- `db:` is an optional prefix indicating that the following path is a DB path. Otherwise it is an object path.
+
+- `segment` is a name of a property (relationship or attribute in Cayenne terms) in the path. Path must have at least one segment; segments are separated by dot (".").
+
+- `+` An "OUTER JOIN" path component. Currently "+" only has effect when translated to SQL as OUTER JOIN. When evaluating expressions in memory, it is ignored.
+
+An object path expression represents a chain of property names rooted in a certain (unspecified during expression creation) object and "navigating" to its related value. E.g. a path expression `artist.name` might be a property path starting from a Painting object, pointing to the related Artist object, and then to its name attribute. A few more examples:
+
+- `name` - can be used to navigate (read) the "name" property of a Person (or any other type of object that has a "name" property).
+
+- `artist.exhibits.closingDate` - can be used to navigate to a closing date of any of the exhibits of a Painting's Artist object.
+
+- `artist.exhibits+.closingDate` - same as the previous example, but when translated into SQL, an OUTER JOIN will be used for "exhibits".
+
+Similarly a database path expression is a dot-separated path through DB table joins and columns. In Cayenne joins are mapped as DbRelationships with some symbolic names (the closest concept to DbRelationship name in the DB world is a named foreign key constraint. But DbRelationship names are usually chosen arbitrarily, without regard to constraints naming or even constraints presence). A database path therefore might look like this - `db:dbrelationshipX.dbrelationshipY.COLUMN_Z`. More specific examples:
+
+- `db:NAME` - can be used to navigate to the value of "NAME" column of some unspecified table.
+
+- `db:artist.artistExhibits.exhibit.CLOSING_DATE` - can be used to match a closing date of any of the exhibits of a related artist record.
+
+Cayenne supports "aliases" in path Expressions. E.g. the same expression can be written using explicit path or an alias:
+
+- `artist.exhibits.closingDate` - full path
+
+- `e.closingDate` - alias `e` is used for `artist.exhibits`.
+
+SelectQuery using the second form of the path expression must be made aware of the alias via `SelectQuery.aliasPathSplits(..)`, otherwise an Exception will be thrown. The main use of aliases is to allow users to control how SQL joins are generated if the same path is encountered more than once in any given Expression. Each alias for any given path would result in a separate join. Without aliases, a single join will be used for a group of matching paths.
+
+==== Creating Expressions from Strings
+
+While in most cases users are likely to rely on API from the following section for expression creation, we'll start by showing String expressions, as this will help to understand the semantics. A Cayenne expression can be represented as a String, which can be converted to an expression object using `ExpressionFactory.exp` static method. Here is an example:
+
+
+[source, java]
+----
+String expString = "name like 'A%' and price < 1000";
+Expression exp = ExpressionFactory.exp(expString);
+----
+
+This particular expression may be used to match Paintings whose names that start with "A" and whose price is less than $1000. While this example is pretty self-explanatory, there are a few points worth mentioning. "name" and "price" here are object paths discussed earlier. As always, paths themselves are not attached to a specific root entity and can be applied to any entity that has similarly named attributes or relationships. So when we are saying that this expression "may be used to match Paintings", we are implying that there may be other entities, for which this expression is valid. Now the expression details...
+
+Character constants that are not paths or numeric values should be enclosed in single or double quotes. Two of the expressions below are equivalent:
+
+[source, java]
+----
+name = 'ABC'
+
+// double quotes are escaped inside Java Strings of course
+name = \"ABC\"
+----
+
+Case sensitivity. Expression operators are case sensitive and are usually lowercase. Complex words follow the Java camel-case style:
+
+[source, java]
+----
+// valid
+name likeIgnoreCase 'A%'
+
+// invalid - will throw a parse exception
+name LIKEIGNORECASE 'A%'
+----
+
+Grouping with parenthesis:
+
+
+[source, java]
+----
+value = (price + 250.00) * 3
+----
+
+Path prefixes. Object expressions are unquoted strings, optionally prefixed by `obj:` (usually they are not prefixed at all actually). Database expressions are always prefixed with `db:`. A special kind of prefix, not discussed yet is `enum:` that prefixes an enumeration constant:
+
+[source, java]
+----
+// object path
+name = 'Salvador Dali'
+
+// same object path - a rarely used form
+obj:name = 'Salvador Dali'
+
+// multi-segment object path
+artist.name = 'Salvador Dali'
+
+// db path
+db:NAME = 'Salvador Dali'
+
+// enumeration constant
+name = enum:org.foo.EnumClass.VALUE1
+----
+
+Binary conditions are expressions that contain a path on the left, a value on the right, and some operation between them, such as equals, like, etc. They can be used as qualifiers in SelectQueries:
+
+[source, java]
+----
+name like 'A%'
+----
+
+
+Named parameters. Expressions can have named parameters (names that start with "$"). Parameterized expressions allow to create reusable expression templates. Also if an Expression contains a complex object that doesn't have a simple String representation (e.g. a Date, a DataObject, an ObjectId), parameterizing such expression is the only way to represent it as String. Here are some examples:
+
+
+[source, java]
+----
+Expression template = Expression.fromString("name = $name");
+...
+Map p1 = Collections.singletonMap("name", "Salvador Dali");
+Expression qualifier1 = template.expWithParameters(p1);
+...
+Map p2 = Collections.singletonMap("name", "Monet");
+Expression qualifier2 = template.expWithParameters(p2);
+----
+
+To create a named parameterized expression with a LIKE clause, SQL wildcards must be part of the values in the Map and not the expression string itself:
+
+[source, java]
+----
+Expression template = Expression.fromString("name like $name");
+...
+Map p1 = Collections.singletonMap("name", "Salvador%");
+Expression qualifier1 = template.expWithParameters(p1);
+----
+
+When matching on a relationship, parameters can be Persistent objects or ObjectIds:
+
+[source, java]
+----
+Expression template = Expression.fromString("artist = $artist");
+...
+Artist dali = // asume we fetched this one already
+Map p1 = Collections.singletonMap("artist", dali);
+Expression qualifier1 = template.expWithParameters(p1);
+----
+
+Uninitialized parameters will be automatically pruned from expressions, so a user can omit some parameters when creating an expression from a parameterized template:
+
+[source, java]
+----
+Expression template = Expression.fromString("name like $name and dateOfBirth > $date");
+...
+Map p1 = Collections.singletonMap("name", "Salvador%");
+Expression qualifier1 = template.expWithParameters(p1);
+
+// qualifier1 is now equals to "name like 'Salvador%'", the 'dateOfBirth' condition was
+// pruned, as no value was specified for the $date parameter
+----
+
+Null handling. Handling of Java nulls as operands is no different from normal values. Instead of using special conditional operators, like SQL does (IS NULL, IS NOT NULL), "=" and "!=" expressions are used directly with null values. It is up to Cayenne to translate expressions with nulls to the valid SQL.
+
+
+NOTE: A formal definition of all possible valid expressions in a form of JavaCC grammar is provided in Appendix C
+
+==== Creating Expressions via API
+
+Creating expressions from Strings is a powerful and dynamic approach, however a safer alternative is to use Java API. It provides some degree of compile-time checking of expressions validity. The API is cenetred around ExpressionFactory class, and the Expression class. ExpressionFactory contains a number of rather self-explanatory factory methods. We won't be going over all of them in detail, but will rather show a few general examples and some gotchas.
+
+The following code recreates the expression from the previous chapter, but now using expression API:
+
+[source, java]
+----
+// String expression: name like 'A%' and price < 1000
+Expression e1 = ExpressionFactory.likeExp("name", "A%");
+Expression e2 = ExpressionFactory.lessExp("price", 1000);
+Expression finalExp = e1.andExp(e2);
+----
+
+This is more verbose than creating it from String, but it is also more resilient to the entity properties renaming and precludes semantic errors in the expression String.
+
+NOTE: The last line in the example above shows how to create a new expression by "chaining" two other epxressions. A common error when chaining expressions is to assume that "andExp" and "orExp" append another expression to the current expression. In fact a new expression is created. I.e. Expression API treats existing expressions as immutable.
+
+As discussed earlier, Cayenne supports aliases in path Expressions, allowing to control how SQL joins are generated if the same path is encountered more than once in the same Expression. Two ExpressionFactory methods allow to implicitly generate aliases to "split" match paths into individual joins if needed:
+
+[source, java]
+----
+Expression matchAllExp(String path, Collection values)
+Expression matchAllExp(String path, Object... values)
+----
+
+"Path" argument to both of these methods can use a split character (a pipe symbol '|') instead of dot to indicate that relationship following a path should be split into a separate set of joins, one per collection value. There can only be one split at most in any given path. Split must always precede a relationship. E.g. `|exhibits.paintings`, `exhibits|paintings`, etc. Internally Cayenne would generate distinct aliases for each of the split expressions, forcing separate joins.
+
+[[evaluete]]
+==== Evaluating Expressions in Memory
+
+When used in a query, an expression is converted to SQL WHERE clause (or ORDER BY clause) by Cayenne during query execution. Thus the actual evaluation against the data is done by the database engine. However the same expressions can also be used for accessing object properties, calculating values, in-memory filtering.
+
+
+Checking whether an object satisfies an expression:
+
+[source, java]
+----
+Expression e = Artist.NAME.in("John", "Bob");
+Artist artist = ...
+if(e.match(artist)) {
+   ...
+}
+----
+
+Reading property value:
+
+
+[source, java]
+----
+Expression e = Expression.fromString(User.NAME_PROPERTY);
+String name = e.evaluate(user);
+----
+
+Filtering a list of objects:
+
+[source, java]
+----
+Expression e = Artist.NAME.in("John", "Bob");
+List<Artist> unfiltered = ...
+List<Artist> filtered = e.filterObjects(unfiltered);
+----
+
+
+NOTE: Current limitation of in-memory expressions is that no collections are permitted in the property path.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/including.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/including.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/including.adoc
new file mode 100644
index 0000000..2999375
--- /dev/null
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/including.adoc
@@ -0,0 +1,394 @@
+// 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.
+
+include::../var.adoc[]
+
+[[include]]
+=== Including Cayenne in a Project
+
+==== Jar Files and Dependencies
+
+Cayenne distribution contains the following core runtime jars in the distribution lib directory:
+
+- `cayenne-server-x.x.jar` - contains full Cayenne runtime (DI, adapters, DB access classes, etc.). Most applications will use only this file.
+
+- `cayenne-client-x.x.jar` - a subset of cayenne-server.jar trimmed for use on the client in an ROP application.
+
+- Other `cayenne-* jars` - various Cayenne extensions.
+
+When using `cayenne-server-x.x.jar` you'll need a few third party jars (all included in `lib/third-party` directory of the distribution):
+
+- http://velocity.apache.org[Apache Velocity Template Engine], version 1.6.x (and all its dependencies bundled with velocity-dep)
+
+- http://commons.apache.org/proper/commons-collections/[Apache Commons Collections], version 3.2.1
+
+- http://commons.apache.org/proper/commons-logging/[Apache Commons Logging], version 1.1
+
+Cayenne integrates with various caching, clustering and other frameworks. These optional integrations will require other third-party jars that the users will need to obtain on their own.
+
+==== Maven Projects
+
+If you are using Maven, you won't have to deal with figuring out the dependencies. You can simply include cayenne-server artifact in your POM:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+   <groupId>org.apache.cayenne</groupId>
+   <artifactId>cayenne-server</artifactId>
+   <version>{version}</version>
+</dependency>
+----
+
+Additionally Cayenne provides a Maven plugin with a set of goals to perform various project tasks, such as synching generated Java classes with the mapping, described in the following subsection. The full plugin name is `org.apache.cayenne.plugins:cayenne-maven-plugin`.
+
+[[cgen]]
+===== cgen
+
+`cgen` is a `cayenne-maven-plugin` goal that generates and maintains source (.java) files of persistent objects based on a DataMap. By default, it is bound to the generate-sources phase. If "makePairs" is set to "true" (which is the recommended default), this task will generate a pair of classes (superclass/subclass) for each ObjEntity in the DataMap. Superclasses should not be changed manually, since they are always overwritten. Subclasses are never overwritten and may be later customized by the user. If "makePairs" is set to "false", a single class will be generated for each ObjEntity.
+
+By creating custom templates, you can use cgen to generate other output (such as web pages, reports, specialized code templates) based on DataMap information.
+
+[#tablecgen.table.table-bordered]
+.cgen required parameters
+[cols="1,1,4"]
+|===
+|Name |Type|Description
+
+.^|map
+.^|File
+a|DataMap XML file which serves as a source of metadata for class generation. E.g.
+[source]
+----
+${project.basedir}/src/main/resources/my.map.xml
+----
+
+.^|destDir
+.^|File
+a|Root destination directory for Java classes (ignoring their package names).
+|===
+
+
+[#cgenOptional.table.table-bordered]
+.cgen optional parameters
+[cols="2,1,6"]
+|===
+|Name |Type|Description
+
+.^|additionalMaps
+.^|File
+.^|A directory that contains additional DataMap XML files that may be needed to resolve cross-DataMap relationships for the the main DataMap, for which class generation occurs.
+
+.^|client
+.^|boolean
+.^|Whether we are generating classes for the client tier in a Remote Object Persistence application. "False" by default.
+
+.^|embeddableTemplate
+.^|String
+.^|Location of a custom Velocity template file for Embeddable class generation. If omitted, default template is used.
+
+.^|embeddableSuperTemplate
+.^|String
+.^|Location of a custom Velocity template file for Embeddable superclass generation. Ignored unless "makepairs" set to "true". If omitted, default template is used.
+
+.^|encoding
+.^|String
+.^|Generated files encoding if different from the default on current platform. Target encoding must be supported by the JVM running the build. Standard encodings supported by Java on all platforms are US-ASCII, ISO-8859-1, UTF-8, UTF-16BE, UTF-16LE, UTF-16. See javadocs for java.nio.charset.Charset for more information.
+
+.^|excludeEntities
+.^|String
+.^|A comma-separated list of ObjEntity patterns (expressed as a perl5 regex) to exclude from template generation. By default none of the DataMap entities are excluded.
+
+.^|includeEntities
+.^|String
+.^|A comma-separated list of ObjEntity patterns (expressed as a perl5 regex) to include from template generation. By default all DataMap entities are included.
+
+.^|makePairs
+.^|boolean
+.^|If "true" (a recommended default), will generate subclass/superclass pairs, with all generated code placed in superclass.
+
+.^|mode
+.^|String
+.^|Specifies class generator iteration target. There are three possible values: "entity" (default), "datamap", "all". "entity" performs one generator iteration for each included ObjEntity, applying either standard to custom entity templates. "datamap" performs a single iteration, applying DataMap templates. "All" is a combination of entity and datamap.
+
+.^|overwrite
+.^|boolean
+.^|Only has effect when "makePairs" is set to "false". If "overwrite" is "true", will overwrite older versions of generated classes.
+
+.^|superPkg
+.^|String
+.^|Java package name of all generated superclasses. If omitted, each superclass will be placed in the subpackage of its subclass called "auto". Doesn't have any effect if either "makepairs" or "usePkgPath" are false (both are true by default).
+
+.^|superTemplate
+.^|String
+.^|Location of a custom Velocity template file for ObjEntity superclass generation. Only has effect if "makepairs" set to "true". If omitted, default template is used.
+
+.^|template
+.^|String
+.^|Location of a custom Velocity template file for ObjEntity class generation. If omitted, default template is used.
+
+.^|usePkgPath
+.^|boolean
+.^|If set to "true" (default), a directory tree will be generated in "destDir" corresponding to the class package structure, if set to "false", classes will be generated in "destDir" ignoring their package.
+
+|===
+
+Example - a typical class generation scenario, where pairs of classes are generated with default Maven source destination and superclass package:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<plugin>
+    <groupId>org.apache.cayenne.plugins</groupId>
+    <artifactId>cayenne-maven-plugin</artifactId>
+    <version>{project-version}</version>
+
+    <!--
+        There's an intermittent problem when using Maven/cgen in Eclipse with  m2eclipse plugin that
+        requires placing "configuration" section at the plugin level, instead of execution
+        level.
+    -->
+    <configuration>
+            <map>${project.basedir}/src/main/resources/my.map.xml</map>
+            <destDir>${project.basedir}/src/main/java</destDir>
+            <superPkg>org.example.model.auto</superPkg>
+    </configuration>
+
+    <executions>
+        <execution>
+            <goals>
+                <goal>cgen</goal>
+            </goals>
+        </execution>
+    </executions>
+</plugin>
+----
+
+===== cdbgen
+
+`cdbgen` is a `cayenne-maven-plugin` goal that drops and/or generates tables in a database on Cayenne DataMap. By default, it is bound to the pre-integration-test phase.
+
+[#cdbgenTable.table.table-bordered]
+.cdbgen required parameters
+[cols="1,1,4"]
+|===
+|Name |Type|Description
+
+.^|map
+.^|File
+a|DataMap XML file which serves as a source of metadata for class generation. E.g.
+[source]
+----
+${project.basedir}/src/main/resources/my.map.xml
+----
+
+.^|driver
+.^|String
+.^|A class of JDBC driver to use for the target database.
+
+.^|url
+.^|String
+.^|JDBC connection URL of a target database.
+|===
+
+[#cdbgenOptionl.table.table-bordered]
+.cdbgen optional parameters
+[cols="1,1,4"]
+|===
+|Name |Type|Description
+
+.^|adapter
+.^|String
+.^|Java class name implementing org.apache.cayenne.dba.DbAdapter. While this attribute is optional (a generic JdbcAdapter is used if not set), it is highly recommended to specify correct target adapter.
+
+
+.^|createFK
+.^|boolean
+.^|Indicates whether cdbgen should create foreign key constraints. Default is "true".
+
+.^|createPK
+.^|boolean
+.^|Indicates whether cdbgen should create Cayenne-specific auto PK objects. Default is "true".
+
+.^|createTables
+.^|boolean
+.^|Indicates whether cdbgen should create new tables. Default is "true".
+
+.^|dropPK
+.^|boolean
+.^|Indicates whether cdbgen should drop Cayenne primary key support objects. Default is "false".
+
+.^|dropTables
+.^|boolean
+.^|Indicates whether cdbgen should drop the tables before attempting to create new ones. Default is "false".
+
+.^|password
+.^|String
+.^|Database user password.
+
+.^|username
+.^|String
+.^|Database user name.
+
+|===
+
+Example - creating a DB schema on a local HSQLDB database:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<plugin>
+    <groupId>org.apache.cayenne.plugins</groupId>
+    <artifactId>maven-cayenne-plugin</artifactId>
+    <version>{version}</version>
+
+    <executions>
+        <execution>
+            <configuration>
+                <map>${project.basedir}/src/main/resources/my.map.xml</map>
+                <url>jdbc:hsqldb:hsql://localhost/testdb</url>
+                <adapter>org.apache.cayenne.dba.hsqldb.HSQLDBAdapter</adapter>
+                <driver>org.hsqldb.jdbcDriver</driver>
+                <username>sa</username>
+            </configuration>
+            <goals>
+                <goal>cdbgen</goal>
+            </goals>
+        </execution>
+    </executions>
+</plugin>
+----
+
+[[mavenCdbimort]]
+===== cdbimport
+
+`cdbimport` is a `maven-cayenne-plugin` goal that generates a DataMap based on an existing database schema. By default, it is bound to the generate-sources phase. This allows you to generate your DataMap prior to building your project, which may be necessary if you are also using the cgen task.
+
+
+[#cdbimportTable.table.table-bordered]
+.cdbimport parameters
+[cols="2,1,2,5"]
+|===
+|Name |Type |Required |Description
+
+.^|map
+.^|File
+.^|Yes
+.^|DataMap XML file which is the destination of the schema import. Can be an existing file. If this file does not exist, it is created when cdbimport is executed. E.g. `${project.basedir}/src/main/resources/my.map.xml`. If "overwrite" is true (the default), an existing DataMap will be used as a template for the new imported DataMap, i.e. all its entities will be cleared and recreated, but its common settings, such as default Java package, will be preserved (unless changed explicitly in the plugin configuration).
+
+.^|driver
+.^|String
+.^|Yes
+.^|A class of JDBC driver to use for the target database.
+
+.^|url
+.^|String
+.^|Yes
+.^|JDBC connection URL of a target database.
+
+.^|adapter
+.^|String
+.^|No
+.^|A Java class name implementing org.apache.cayenne.dba.DbAdapter. This attribute is optional. If not specified, AutoAdapter is used, which will attempt to guess the DB type.
+
+.^|importProcedures
+.^|boolean
+.^|No
+.^|Indicates whether stored procedures should be imported from the database. Default is false.
+
+.^|meaningfulPk
+.^|boolean
+.^|No
+.^|Indicates whether primary keys should be mapped as attributes of the ObjEntity. Default is false.
+
+.^|namingStrategy
+.^|String
+.^|No
+.^|The naming strategy used for mapping database names to object entity names. Default is `org.apache.cayenne.map.naming.SmartNamingStrategy`.
+
+.^|overwriteExisting
+.^|boolean
+.^|No
+.^|Indicates whether existing DB and object entities should be overwritten. This is an all-or-nothing setting. If you need finer granularity, use the CayenneModeler. Default is "true".
+
+.^|password
+.^|String
+.^|No
+.^|Database user password.
+
+.^|procedurePattern
+.^|String
+.^|No
+.^|Pattern to match stored procedure names against for import. Default is to match all stored procedures. This value is only meaningful if importProcedures is true.
+
+.^|schemaName
+.^|String
+.^|No
+.^|Database schema to import tables/stored procedures from.
+
+.^|tablePattern
+.^|String
+.^|No
+.^|Pattern to match table names against for import. Default is to match all tables.
+
+.^|username
+.^|String
+.^|No
+.^|Database user name.
+
+|===
+
+Example - loading a DB schema from a local HSQLDB database (essentially a reverse operation compared to the cdbgen example above) :
+
+[source, XML,,subs="verbatim,attributes"]
+----
+<plugin>
+    <groupId>org.apache.cayenne.plugins</groupId>
+    <artifactId>cayenne-maven-plugin</artifactId>
+    <version>{version}</version>
+
+    <executions>
+        <execution>
+            <configuration>
+                <map>${project.basedir}/src/main/resources/my.map.xml</map>
+                <url>jdbc:mysql://127.0.0.1/mydb</url>
+                <adapter>org.apache.cayenne.dba.hsqldb.HSQLDBAdapter</adapter>
+                <driver>com.mysql.jdbc.Driver</driver>
+                <username>sa</username>
+            </configuration>
+            <goals>
+                <goal>cdbimport</goal>
+            </goals>
+        </execution>
+    </executions>
+</plugin>
+----
+
+==== Ant Projects
+
+===== cgen
+
+===== cdbgen
+
+===== cdbimport
+
+This is an Ant counterpart of "cdbimport" goal of cayenne-maven-plugin described above. It has exactly the same properties. Here is a usage example:
+
+[source, XML]
+----
+ <cdbimport map="${context.dir}/WEB-INF/my.map.xml"
+     driver="com.mysql.jdbc.Driver"
+     url="jdbc:mysql://127.0.0.1/mydb"
+     username="sa"/>
+----
+
+===== cdataport
+

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
new file mode 100644
index 0000000..6102f0c
--- /dev/null
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
@@ -0,0 +1,280 @@
+// 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.
+
+=== Lifecycle Events
+
+An application might be interested in getting notified when a Persistent object moves through its lifecycle (i.e. fetched from DB, created, modified, committed). E.g. when a new object is created, the application may want to initialize its default properties (this can't be done in constructor, as constructor is also called when an object is fetched from DB). Before save, the application may perform validation and/or set some properties (e.g. "updatedTimestamp"). After save it may want to create an audit record for each saved object, etc., etc.
+
+All this can be achieved by declaring callback methods either in Persistent objects or in non-persistent listener classes defined by the application (further simply called "listeners"). There are eight types of lifecycle events supported by Cayenne, listed later in this chapter. When any such event occurs (e.g. an object is committed), Cayenne would invoke all appropriate callbacks. Persistent objects would receive their own events, while listeners would receive events from any objects.
+
+Cayenne allows to build rather powerful and complex "workflows" or "processors" tied to objects lifecycle, especially with listeners, as they have full access to the application evnironment outside Cayenne. This power comes from such features as filtering which entity events are sent to a given listener and the ability to create a common operation context for multiple callback invocations. All of these are discussed later in this chapter.
+
+==== Types of Lifecycle Events
+
+Cayenne defines the following 8 types of lifecycle events for which callbacks can be regsitered:
+
+[#lifecycleEvent.table.table-bordered]
+.Lifecycle Event Types
+[cols="1,4"]
+|===
+|Event |Occurs...
+
+.^|PostAdd
+.^|right after a new object is created inside `ObjectContext.newObject()`. When this event is fired the object is already registered with its ObjectContext and has its ObjectId and ObjectContext properties set.
+
+.^|PrePersist
+.^|right before a new object is committed, inside `ObjectContext.commitChanges()` and `ObjectContext.commitChangesToParent()` (and after `"validateForInsert()"`).
+
+.^|PreUpdate
+.^|right before a modified object is committed, inside `ObjectContext.commitChanges()` and `ObjectContext.commitChangesToParent()` (and after `"validateForUpdate()"`).
+
+.^|PreRemove
+.^|right before an object is deleted, inside `ObjectContext.deleteObjects()`. The event is also generated for each object indirectly deleted as a result of CASCADE delete rule.
+
+.^|PostPersist
+.^|right after a commit of a new object is done, inside `ObjectContext.commitChanges()`.
+
+.^|PostUpdate
+.^|right after a commit of a modified object is done, inside `ObjectContext.commitChanges()`.
+
+.^|PostRemove
+.^|right after a commit of a deleted object is done, inside `ObjectContext.commitChanges()`.
+
+.^|PostLoad
+a|
+- After an object is fetched inside ObjectContext.performQuery().
+- After an object is reverted inside ObjectContext.rollbackChanges().
+- Anytime a faulted object is resolved (i.e. if a relationship is fetched).
+|===
+
+==== Callbacks on Persistent Objects
+
+Callback methods on Persistent classes are mapped in CayenneModeler for each ObjEntity. Empty callback methods are automatically created as a part of class generation (either with Maven, Ant or the Modeler) and are later filled with appropriate logic by the programmer. E.g. assuming we mapped a 'post-add' callback called 'onNewOrder' in ObjEntity 'Order', the following code will be generated:
+
+[source, Java]
+----
+public abstract class _Order extends CayenneDataObject {
+    protected abstract void onNewOrder();
+}
+
+public class Order extends _Order {
+
+    @Override
+    protected void onNewOrder() {
+        //TODO: implement onNewOrder
+    }
+}
+----
+
+As `onNewOrder()` is already declared in the mapping, it does not need to be registered explicitly. Implementing the method in subclass to do something meaningful is all that is required at this point.
+
+As a rule callback methods do not have any knowledge of the outside application, and can only access the state of the object itself and possibly the state of other persistent objects via object's own ObjectContext.
+
+NOTE: Validation and callbacks: There is a clear overlap in functionality between object callbacks and `DataObject.validateForX()` methods. In the future validation may be completely superceeded by callbacks. It is a good idea to use "validateForX" strictly for validation (or not use it at all). Updating the state before commit should be done via callbacks.
+
+==== Callbacks on Non-Persistent Listeners
+
+NOTE: While listener callback methods can be declared in the Modeler (at least as of this wrting), which ensures their automatic registration in runtime, there's a big downside to it. The power of the listeners lies in their complete separation from the XML mapping. The mapping once created, can be reused in different contexts each having a different set of listeners. Placing a Java class of the listener in the XML mapping, and relying on Cayenne to instantiate the listeners severly limits mapping reusability. Further down in this chapter we'll assume that the listener classes are never present in the DataMap and are registered via API.
+
+A listener is simply some application class that has one or more annotated callback methods. A callback method signature should be `void someMethod(SomePersistentType object)`. It can be public, private, protected or use default access:
+
+[source, Java]
+----
+ public class OrderListener {
+
+   @PostAdd(Order.class)
+   public void setDefaultsForNewOrder(Order o) {
+      o.setCreatedOn(new Date());
+   }
+}
+----
+
+Notice that the example above contains an annotation on the callback method that defines the type of the event this method should be called for. Before we go into annotation details, we'll show how to create and register a listener with Cayenne. It is always a user responsibility to register desired application listeners, usually right after ServerRuntime is started. Here is an example:
+
+First let's define 2 simple listeners.
+
+[source, Java]
+----
+public class Listener1 {
+
+    @PostAdd(MyEntity.class)
+    void postAdd(Persistent object) {
+        // do something
+    }
+}
+
+public class Listener2 {
+
+    @PostRemove({ MyEntity1.class, MyEntity2.class })
+    void postRemove(Persistent object) {
+        // do something
+    }
+
+    @PostUpdate({ MyEntity1.class, MyEntity2.class })
+    void postUpdate(Persistent object) {
+        // do something
+    }
+}
+----
+
+Ignore the annotations for a minute. The important point here is that the listeners are arbitrary classes unmapped and unknown to Cayenne, that contain some callback methods. Now let's register them with runtime:
+
+[source, Java]
+----
+ServerRuntime runtime = ...
+
+LifecycleCallbackRegistry registry =
+    runtime.getDataDomain().getEntityResolver().getCallbackRegistry();
+
+registry.addListener(new Listener1());
+registry.addListener(new Listener2());
+----
+
+
+Listeners in this example are very simple. However they don't have to be. Unlike Persistent objects, normally listeners initialization is managed by the application code, not Cayenne, so listeners may have knowledge of various application services, operation transactional context, etc. Besides a single listener can apply to multiple entities. As a consequence their callbacks can do more than just access a single ObjectContext.
+
+Now let's discuss the annotations. There are eight annotations exactly matching the names of eight lifecycle events. A callback method in a listener should be annotated with at least one, but possibly with more than one of them. Annotation itself defines what event the callback should react to. Annotation parameters are essentially an entity filter, defining a subset of ObjEntities whose events we are interested in:
+
+[source, Java]
+----
+// this callback will be invoked on PostRemove event of any object
+// belonging to MyEntity1, MyEntity2 or their subclasses
+@PostRemove({ MyEntity1.class, MyEntity2.class })
+void postRemove(Persistent object) {
+    ...
+}
+----
+
+[source, Java]
+----
+// similar example with multipe annotations on a single method
+// each matching just one entity
+@PostPersist(MyEntity1.class)
+@PostRemove(MyEntity1.class)
+@PostUpdate(MyEntity1.class)
+void postCommit(MyEntity1 object) {
+    ...
+}
+----
+
+As shown above, "value" (the implicit annotation parameter) can contain one or more entity classes. Only these entities' events will result in callback invocation. There's also another way to match entities - via custom annotations. This allows to match any number of entities without even knowing what they are. Here is an example. We'll first define a custom annotation:
+
+[source, Java]
+----
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Tag {
+
+}
+----
+
+Now we can define a listener that will react to events from ObjEntities annotated with this annotation:
+
+[source, Java]
+----
+public class Listener3 {
+
+    @PostAdd(entityAnnotations = Tag.class)
+    void postAdd(Persistent object) {
+        // do something
+    }
+}
+----
+
+As you see we don't have any entities yet, still we can define a listener that does something useful. Now let's annotate some entities:
+
+[source, Java]
+----
+@Tag
+public class MyEntity1 extends _MyEntity1 {
+
+}
+
+@Tag
+public class MyEntity2 extends _MyEntity2 {
+
+}
+----
+
+
+==== Combining Listeners with DataChannelFilters
+
+A final touch in the listeners design is preserving the state of the listener within a single select or commit, so that events generated by multiple objects can be collected and processed all together. To do that you will need to implement a `DataChannelFilter`, and add some callback methods to it. They will store their state in a ThreadLocal variable of the filter. Here is an example filter that does something pretty meaningless - counts how many total objects were committed. However it demonstrates the important pattern of aggregating multiple events and presenting a combined result:
+
+[source, Java]
+----
+public class CommittedObjectCounter implements DataChannelFilter {
+
+    private ThreadLocal<int[]> counter;
+
+    @Override
+    public void init(DataChannel channel) {
+        counter = new ThreadLocal<int[]>();
+    }
+
+    @Override
+    public QueryResponse onQuery(ObjectContext originatingContext, Query query, DataChannelFilterChain filterChain) {
+        return filterChain.onQuery(originatingContext, query);
+    }
+
+    @Override
+    public GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes, int syncType,
+            DataChannelFilterChain filterChain) {
+
+        // init the counter for the current commit
+        counter.set(new int[1]);
+
+        try {
+            return filterChain.onSync(originatingContext, changes, syncType);
+        } finally {
+
+            // process aggregated result and release the counter
+            System.out.println("Committed " + counter.get()[0] + " object(s)");
+            counter.set(null);
+        }
+    }
+
+    @PostPersist(entityAnnotations = Tag.class)
+    @PostUpdate(entityAnnotations = Tag.class)
+    @PostRemove(entityAnnotations = Tag.class)
+    void afterCommit(Persistent object) {
+        counter.get()[0]++;
+    }
+}
+----
+
+Now since this is both a filter and a listener, it needs to be registered as such:
+
+[source, Java]
+----
+CommittedObjectCounter counter = new CommittedObjectCounter();
+
+ServerRuntime runtime = ...
+DataDomain domain = runtime.getDataDomain();
+
+// register filter
+domain.addFilter(counter);
+
+// register listener
+domain.getEntityResolver().getCallbackRegistry().addListener(counter);
+----
+
+
+
+
+
+
+
+
+

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc
new file mode 100644
index 0000000..9424a70
--- /dev/null
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc
@@ -0,0 +1,309 @@
+// 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.
+
+=== Persistent Objects and ObjectContext
+
+==== ObjectContext
+
+ObjectContext is an interface that users normally work with to access the database. It provides the API to execute database operations and to manage persistent objects. A context is obtained from the ServerRuntime:
+
+[source, java]
+----
+ObjectContext context = runtime.getContext();
+----
+
+The call above creates a new instance of ObjectContext that can access the database via this runtime. ObjectContext is a single "work area" in Cayenne, storing persistent objects. ObjectContext guarantees that for each database row with a unique ID it will contain at most one instance of an object, thus ensuring object graph consistency between multiple selects (a feature called "uniquing"). At the same time different ObjectContexts will have independent copies of objects for each unique database row. This allows users to isolate object changes from one another by using separate ObjectContexts.
+
+These properties directly affect the strategies for scoping and sharing (or not sharing) ObjectContexts. Contexts that are only used to fetch objects from the database and whose objects are never modified by the application can be shared between mutliple users (and multiple threads). Contexts that store modified objects should be accessed only by a single user (e.g. a web application user might reuse a context instance between multiple web requests in the same HttpSession, thus carrying uncommitted changes to objects from request to request, until he decides to commit or rollback them). Even for a single user it might make sense to use mutliple ObjectContexts (e.g. request-scoped contexts to allow concurrent requests from the browser that change and commit objects independently).
+
+ObjectContext is serializable and does not permanently hold to any of the application resources. So it does not have to be closed. If the context is not used anymore, it should simply be allowed to go out of scope and get garbage collected, just like any other Java object.
+
+
+==== Persistent Object and its Lifecycle
+
+Cayenne can persist Java objects that implement `org.apache.cayenne.Persistent` interface. Generally persistent classes are generated from the model as described above, so users do not have to worry about superclass and property implementation details.
+
+Persistent interface provides access to 3 persistence-related properties - objectId, persistenceState and objectContext. All 3 are initialized by Cayenne runtime framework. Application code should not attempt to change them. However it is allowed to read them, which provides valuable runtime information. E.g. ObjectId can be used for quick equality check of 2 objects, knowing persistence state would allow highlighting changed objects, etc.
+
+Each persistent object belongs to a single ObjectContext, and can be in one of the following persistence states (as defined in `org.apache.cayenne.PersistenceState`) :
+
+[#persistenceStates.table.table-bordered]
+.Persistence States
+// ^.^ is not a funny face it's Asciidoctor alignment syntax (center both vertical and horizontal)
+[cols="^.^1,4"]
+|===
+
+.^|TRANSIENT
+.^|The object is not registered with an ObjectContext and will not be persisted.
+
+.^|NEW
+.^|The object is freshly registered in an ObjectContext, but has not been saved to the database yet and there is no matching database row.
+
+.^|COMMITED
+.^|The object is registered in an ObjectContext, there is a row in the database corresponding to this object, and the object state corresponds to the last known state of the matching database row.
+
+.^|MODIFIED
+.^|The object is registered in an ObjectContext, there is a row in the database corresponding to this object, but the object in-memory state has diverged from the last known state of the matching database row.
+
+.^|HOLLOW
+.^|The object is registered in an ObjectContext, there is a row in the database corresponding to this object, but the object state is unknown. Whenever an application tries to access a property of such object, Cayenne attempts reading its values from the database and "inflate" the object, turning it to COMMITED.
+
+.^|DELETED
+.^|The object is registered in an ObjectContext and has been marked for deletion in-memory. The corresponding row in the database will get deleted upon ObjectContext commit, and the object state will be turned into TRANSIENT.
+|===
+
+==== ObjectContext Persistence API
+
+One of the first things users usually want to do with an ObjectContext is to select some objects from a database. This is done by calling "performQuery" method:
+
+[source, java]
+----
+SelectQuery query = new SelectQuery(Artist.class);
+List<Artist> artists = context.performQuery(query);
+----
+
+We'll discuss queries in some detail in the following chapters. The example above is self-explanatory - we create a SelectQuery that matches all Artist objects present in the database, and then call "performQuery", getting a list of Artist objects.
+
+Some queries can be quite complex, returning multiple result sets or even updating the database. For such queries ObjectContext provides "performGenericQuery"method. While not nearly as commonly-used as "performQuery", it is nevertheless important in some situations. E.g.:
+
+[source, java]
+----
+Collection<Query> queries = ... // multiple queries that need to be run together
+QueryChain query = new QueryChain(queries);
+
+QueryResponse response = context.performGenericQuery(query);
+----
+
+
+An application might modify selected objects. E.g.:
+
+[source, java]
+----
+Artist selectedArtist = artists.get(0);
+selectedArtist.setName("Dali");
+----
+
+The first time the object property is changed, the object's state is automatically set to "MODIFIED" by Cayenne. Cayenne tracks all in-memory changes until a user calls "commitChanges":
+
+[source, java]
+----
+context.commitChanges();
+----
+
+At this point all in-memory changes are analyzed and a minimal set of SQL statements is issued in a single transaction to synchronize the database with the in-memory state. In our example "commitChanges" commits just one object, but generally it can be any number of objects.
+
+If instead of commit, we wanted to reset all changed objects to the previously committed state, we'd call `rollbackChanges` instead:
+
+[source, java]
+----
+context.rollbackChanges();
+----
+
+"newObject" method call creates a persistent object and sets its state to "NEW":
+
+[source, java]
+----
+Artist newArtist = context.newObject(Artist.class);
+newArtist.setName("Picasso");
+----
+
+It will only exist in memory until "commitChanges" is issued. On commit Cayenne might generate a new primary key (unless a user set it explicitly, or a PK was inferred from a relationship) and issue an INSERT SQL statement to permanently store the object.
+
+`deleteObjects` method takes one or more Persistent objects and marks them as "DELETED":
+
+[source, java]
+----
+context.deleteObjects(artist1);
+context.deleteObjects(artist2, artist3, artist4);
+----
+
+Additionally "deleteObjects" processes all delete rules modeled for the affected objects. This may result in implicitly deleting or modifying extra related objects. Same as insert and update, delete operations are sent to the database only when "commitChanges" is called. Similarly "rollbackChanges" will undo the effect of "newObject" and "deleteObjects".
+
+`localObject` returns a copy of a given persistent object that is "local" to a given ObjectContext:
+
+Since an application often works with more than one context, "localObject" is a rather common operation. E.g. to improve performance a user might utilize a single shared context to select and cache data, and then occasionally transfer some selected objects to another context to modify and commit them:
+
+
+[source, java]
+----
+ObjectContext editingContext = runtime.newContext();
+Artist localArtist = editingContext.localObject(artist);
+----
+
+Often an appliction needs to inspect mapping metadata. This information is stored in the EntityResolver object, accessible via the ObjectContext:
+
+[source, java]
+----
+EntityResolver resolver = objectContext.getEntityResolver();
+----
+
+Here we discussed the most commonly used subset of the ObjectContext API. There are other useful methods, e.g. those allowing to inspect registered objects state in bulk, etc. Check the latest JavaDocs for details.
+
+==== Cayenne Helper Class
+
+There is a useful helper class called "Cayenne" (fully-qualified name `"org.apache.cayenne.Cayenne"`) that builds on ObjectContext API to provide a number of very common operations. E.g. get a primary key (most entities do not model PK as an object property) :
+
+[source, java]
+----
+long pk = Cayenne.longPKForObject(artist);
+----
+
+It also provides the reverse operation - finding an object given a known PK:
+
+[source, java]
+----
+Artist artist = Cayenne.objectForPK(context, Artist.class, 34579);
+----
+
+If a query is expected to return 0 or 1 object, Cayenne helper class can be used to find this object. It throws an exception if more than one object matched the query:
+
+[source, java]
+----
+Artist artist = (Artist) Cayenne.objectForQuery(context, new SelectQuery(Artist.class));
+----
+
+Feel free to explore Cayenne class API for other useful methods.
+
+==== ObjectContext Nesting
+In all the examples shown so far an ObjectContext would directly connect to a database to select data or synchronize its state (either via commit or rollback). However another context can be used in all these scenarios instead of a database. This concept is called ObjectContext "nesting". Nesting is a parent/child relationship between two contexts, where child is a nested context and selects or commits its objects via a parent.
+
+Nesting is useful to create isolated object editing areas (child contexts) that need to all be committed to an intermediate in-memory store (parent context), or rolled back without affecting changes already recorded in the parent. Think cascading GUI dialogs, or parallel AJAX requests coming to the same session.
+
+In theory Cayenne supports any number of nesting levels, however applications should generally stay with one or two, as deep hierarchies will most certainly degrade the performance of the deeply nested child contexts. This is due to the fact that each context in a nesting chain has to update its own objects during most operations.
+
+Cayenne ROP is an extreme case of nesting when a child context is located in a separate JVM and communicates with its parent via a web service. ROP is discussed in details in the following chapters. Here we concentrate on the same-VM nesting.
+
+To create a nested context, use an instance of ServerRuntime, passing it the desired parent:
+
+[source, java]
+----
+ObjectContext parent = runtime.getContext();
+ObjectContext nested = runtime.getContext((DataChannel) parent);
+----
+
+From here a nested context operates just like a regular context (you can perform queries, create and delete objects, etc.). The only difference is that commit and rollback operations can either be limited to synchronization with the parent, or cascade all the way to the database:
+
+[source, java]
+----
+// merges nested context changes into the parent context
+nested.commitChangesToParent();
+
+// regular 'commitChanges' cascades commit through the chain
+// of parent contexts all the way to the database
+nested.commitChanges();
+----
+
+[source, java]
+----
+// unrolls all local changes, getting context in a state identical to parent
+nested.rollbackChangesLocally();
+
+// regular 'rollbackChanges' cascades rollback through the chain of contexts
+// all the way to the topmost parent
+nested.rollbackChanges();
+----
+
+==== Generic Persistent Objects
+
+As described in the CayenneModeler chapter, Cayenne supports mapping of completely generic classes to specific entities. Although for conveniece most applications should stick with entity-specific class mappings, the generic feature offers some interesting possibilities, such as creating mappings completely on the fly in a running application, etc.
+
+Generic objects are first class citizens in Cayenne, and all common persistent operations apply to them as well. There are some pecularities however, described below.
+
+When creating a new generic object, either cast your ObjectContext to DataContext (that provides "newObject(String)" API), or provide your object with an explicit ObjectId:
+
+[source, java]
+----
+DataObject generic = ((DataContext) context).newObject("GenericEntity");
+----
+
+[source, java]
+----
+DataObject generic = new CayenneDataObject();
+generic.setObjectId(new ObjectId("GenericEntity"));
+context.registerNewObject(generic);
+----
+
+SelectQuery for generic object should be created passing entity name String in constructor, instead of a Java class:
+
+[source, java]
+----
+SelectQuery query = new SelectQuery("GenericEntity");
+----
+
+Use DataObject API to access and modify properties of a generic object:
+
+[source, java]
+----
+String name = (String) generic.readProperty("name");
+generic.writeProperty("name", "New Name");
+----
+
+This is how an application can obtain entity name of a generic object:
+
+[source, java]
+----
+String entityName = generic.getObjectId().getEntityName();
+----
+
+
+==== Transactions
+
+Considering how much attention is given to managing transactions in most other ORMs, transactions have been conspicuously absent from the ObjectContext discussion till now. The reason is that transactions are seamless in Cayenne in all but a few special cases. ObjectContext is an in-memory container of objects that is disconnected from the database, except when it needs to run an operation. So it does not care about any surrounding transaction scope. Sure enough all database operations are transactional, so when an application does a commit, all SQL execution is wrapped in a database transaction. But this is done behind the scenes and is rarely a concern to the application code.
+
+Two cases where transactions need to be taken into consideration are container-managed and application-managed transactions.
+
+If you are using an EJB container (or some other JTA environment), you'll likely need to switch Cayenne runtime into "external transactions mode". This is either done in the Modeler (check DataDomain > 'Container-Managed Transactions' checkbox), or in the code:
+
+[source, java]
+----
+runtime.getDataDomain().setUsingExternalTransactions(true);
+----
+
+In this case Cayenne assumes that JDBC Connections obtained by runtime whenever that might happen are all coming from a transactional DataSource managed by the container. In this case Cayenne does not attempt to commit or rollback the connections, leaving it up to the container to do that when appropriate.
+
+In the second scenario, an application might need to define its own transaction scope that spans more than one Cayenne operation. E.g. two sequential commits that need to be rolled back together in case of failure. This can be done with an explicit thread-bound transaction that surrounds a set of operations. Application is responsible for committing or rolling it back:
+
+[source, java]
+----
+Transaction tx = runtime.getDataDomain().createTransaction();
+Transaction.bindThreadTransaction(tx);
+
+try {
+    // commit one or more contexts
+    context1.commitChanges();
+    context2.commitChanges();
+    ....
+    // after changing some objects in context1, commit again
+    context1.commitChnages();
+    ....
+    // if no failures, commit
+    tx.commit();
+}
+catch (Exception ex) {
+    tx.setRollbackOnly();
+}
+finally {
+    Transaction.bindThreadTransaction(null);
+
+    if (tx.getStatus() == Transaction.STATUS_MARKED_ROLLEDBACK) {
+        try {
+           tx.rollback();
+        }
+        catch (Exception rollbackEx) {
+        }
+    }
+}
+----
+
+

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/orderings.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/orderings.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/orderings.adoc
new file mode 100644
index 0000000..6b9b57a
--- /dev/null
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/orderings.adoc
@@ -0,0 +1,36 @@
+// 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.
+
+=== Orderings
+
+An Ordering object defines how a list of objects should be ordered. Orderings are essentially path expressions combined with a sorting strategy. Creating an Ordering:
+
+[source, java]
+----
+Ordering o = new Ordering(Painting.NAME_PROPERTY, SortOrder.ASCENDING);
+----
+
+Like expressions, orderings are translated into SQL as parts of queries (and the sorting occurs in the database). Also like expressions, orderings can be used in memory, naturally - to sort objects:
+
+[source, java]
+----
+Ordering o = new Ordering(Painting.NAME_PROPERTY, SortOrder.ASCENDING_INSENSITIVE);
+List<Painting> list = ...
+o.orderList(list);
+----
+
+Note that unlike filtering with Expressions, ordering is performed in-place. This list object is reordered and no new list is created.
+
+
+


Mime
View raw message