This is an automated email from the ASF dual-hosted git repository.
ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne-website.git
The following commit(s) were added to refs/heads/master by this push:
new f9bf6cc6e Update docs for Cayenne 4.2
f9bf6cc6e is described below
commit f9bf6cc6e58724b3101f134137a4c24d54b14fb0
Author: Nikita Timofeev <[email protected]>
AuthorDate: Fri Feb 9 11:57:04 2024 +0400
Update docs for Cayenne 4.2
---
src/main/site/content/docs/4.2/cayenne-guide.html | 162 +++++++++++-----------
1 file changed, 81 insertions(+), 81 deletions(-)
diff --git a/src/main/site/content/docs/4.2/cayenne-guide.html
b/src/main/site/content/docs/4.2/cayenne-guide.html
index 4d3b1a38e..7f4b589da 100644
--- a/src/main/site/content/docs/4.2/cayenne-guide.html
+++ b/src/main/site/content/docs/4.2/cayenne-guide.html
@@ -59,12 +59,12 @@ menu:
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p
class="tableblock">4.2</p></td>
- <td class="tableblock halign-left valign-top"><p
class="tableblock">Java 1.8 or newer</p></td>
- <td class="tableblock halign-left valign-top"><p
class="tableblock">Release Candidate</p></td>
+ <td class="tableblock halign-left valign-top"><p
class="tableblock">Java 8 or newer</p></td>
+ <td class="tableblock halign-left valign-top"><p
class="tableblock">Stable</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p
class="tableblock">4.1</p></td>
- <td class="tableblock halign-left valign-top"><p
class="tableblock">Java 1.8 or newer</p></td>
+ <td class="tableblock halign-left valign-top"><p
class="tableblock">Java 8 or newer</p></td>
<td class="tableblock halign-left valign-top"><p
class="tableblock">Stable</p></td>
</tr>
<tr>
@@ -207,7 +207,7 @@ total 24
</div>
</div>
<div class="paragraph">
- <p>Map files are resolved by Cayenne by appending ".map.xml" extension to
the map name, and resolving the resulting string relative to the root
descriptor URI. The following sections discuss varios ORM model objects,
without regards to their XML representation. XML format details are really
unimportant to the Cayenne users.</p>
+ <p>Map files are resolved by Cayenne by appending ".map.xml" extension to
the map name, and resolving the resulting string relative to the root
descriptor URI. The following sections discuss various ORM model objects,
without regards to their XML representation. XML format details are really
unimportant to the Cayenne users.</p>
</div>
</div>
<div class="sect3">
@@ -315,7 +315,7 @@ total 24
<div class="sect3">
<h4 id="modeling-generic-persistent-classes"><a class="anchor"
href="#modeling-generic-persistent-classes"></a>1.3.4. Modeling Generic
Persistent Classes</h4>
<div class="paragraph">
- <p>Normally each ObjEntity is mapped to a specific Java class (such as
Artist or Painting) that explicitly declare all entity properties as pairs of
getters and setters. However Cayenne allows to map a completly generic class to
any number of entities. The only expectation is that a generic class implements
org.apache.cayenne.DataObject. So an ideal candidate for a generic class is
CayenneDataObject, or some custom subclass of CayenneDataObject.</p>
+ <p>Normally each ObjEntity is mapped to a specific Java class (such as
Artist or Painting) that explicitly declare all entity properties as pairs of
getters and setters. However Cayenne allows to map a completely generic class
to any number of entities. The only expectation is that a generic class
implements org.apache.cayenne.DataObject. So an ideal candidate for a generic
class is CayenneDataObject, or some custom subclass of CayenneDataObject.</p>
</div>
<div class="paragraph">
<p>If you don’t enter anything for Java Class of an ObjEntity, Cayenne
assumes generic mapping and uses the following implicit rules to determine a
class of a generic object. If DataMap "Custom Superclass" is set, runtime uses
this class to instantiate new objects. If not,
<code>org.apache.cayenne.CayenneDataObject</code> is used.</p>
@@ -460,10 +460,10 @@ ServerRuntime runtime = ServerRuntime.builder()
<div class="sect3">
<h4 id="web-applications"><a class="anchor"
href="#web-applications"></a>2.2.3. Web Applications</h4>
<div class="paragraph">
- <p>Web applications can use a variety of mechanisms to configure and
start the "services" they need, Cayenne being one of such services.
Configuration can be done within standard Servlet specification objects like
Servlets, Filters, or ServletContextListeners, or can use Spring, JEE CDI, etc.
This is a user’s architectural choice and Cayenne is agnostic to it and will
happily work in any environment. As described above, all that is needed is to
create an instance of ServerRuntime so [...]
+ <p>Web applications can use a variety of mechanisms to configure and
start the "services" they need, Cayenne being one of such services.
Configuration can be done within standard servlet specification objects like
Servlets, Filters, or ServletContextListeners, or can use Spring, JEE CDI, etc.
This is a user’s architectural choice and Cayenne is agnostic to it and will
happily work in any environment. As described above, all that is needed is to
create an instance of ServerRuntime so [...]
</div>
<div class="paragraph">
- <p>Still Cayenne includes a piece of web app configuration code that can
assist in quickly setting up simple Cayenne-enabled web applications. We are
talking about CayenneFilter. It is declared in web.xml:</p>
+ <p>Still Cayenne includes a piece of web app configuration code that can
assist in quickly setting up simple Cayenne-enabled web applications. We are
talking about <code>CayenneFilter</code>. It is declared in
<code>web.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -482,10 +482,10 @@ ServerRuntime runtime = ServerRuntime.builder()
</div>
</div>
<div class="paragraph">
- <p>When started by the web container, it creates a instance of
ServerRuntime and stores it in the ServletContext. Note that the name of
Cayenne XML project file is derived from the "filter-name". In the example
above CayenneFilter will look for an XML file "cayenne-project.xml". This can
be overridden with "configuration-location" init parameter.</p>
+ <p>When started by the web container, it creates a instance of
ServerRuntime and stores it in the ServletContext. Note that the name of a
Cayenne XML project file is derived from the "filter-name". In the example
above, CayenneFilter will look for an XML file "cayenne-project.xml". This can
be overridden with the "configuration-location" init parameter.</p>
</div>
<div class="paragraph">
- <p>When the application runs, all HTTP requests matching the filter
url-pattern will have access to a session-scoped ObjectContext like this:</p>
+ <p>When the application runs, all HTTP requests matching the filter
url-pattern have access to a session-scoped ObjectContext like this:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -493,17 +493,17 @@ ServerRuntime runtime = ServerRuntime.builder()
</div>
</div>
<div class="paragraph">
- <p>Of course the ObjectContext scope, and other behavior of the Cayenne
runtime can be customized via dependency injection. For this another filter
init parameter called "extra-modules" is used. "extra-modules" is a comma or
space-separated list of class names, with each class implementing Module
interface. These optional custom modules are loaded after the the standard
ones, which allows users to override all standard definitions.</p>
+ <p>Of course, the ObjectContext scope and other behavior of the Cayenne
runtime can be customized via dependency injection. For this, another filter
init parameter called "extra-modules" is used. "extra-modules" is a comma- or
space-separated list of class names, with each class implementing Module
interface. These optional custom modules are loaded after the standard ones,
which allows users to override all standard definitions.</p>
</div>
<div class="paragraph">
- <p>For those interested in the DI container contents of the runtime
created by CayenneFilter, it is the same ServerRuntime as would’ve been created
by other means, but with an extra
<code>org.apache.cayenne.configuration.web.WebModule</code> module that
provides <code>org.apache.cayenne.configuration.web.RequestHandler</code>
service. This is the service to override in the custom modules if you need to
provide a different ObjectContext scope, etc.</p>
+ <p>For those interested in the DI container contents of the runtime
created by <code>CayenneFilter</code>, it is the same ServerRuntime as would
have been created by other means, but with an extra
<code>org.apache.cayenne.configuration.web.WebModule</code> module that
provides the <code>org.apache.cayenne.configuration.web.RequestHandler</code>
service. This is the service to override in the custom modules if you need to
provide a different ObjectContext scope, etc.</p>
</div>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa fa-info-circle fa-2x" title="Note"></i>
</td>
- <td class="content"> You should not think of CayenneFilter as the only
way to start and use Cayenne in a web application. In fact CayenneFilter is
entirely optional. Use it if you don’t have any special design for application
service management. If you do, simply integrate Cayenne into that design. </td>
+ <td class="content"> You should not think of
<code>CayenneFilter</code> as the only way to start and use Cayenne in a web
application. In fact, <code>CayenneFilter</code> is entirely optional. Use it
if you don’t have any special design for application service management. If you
do, simply integrate Cayenne into that design. </td>
</tr>
</tbody>
</table>
@@ -523,22 +523,22 @@ ServerRuntime runtime = ServerRuntime.builder()
</div>
</div>
<div class="paragraph">
- <p>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 eac [...]
+ <p>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 [...]
</div>
<div class="paragraph">
- <p>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 c [...]
+ <p>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 multiple 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 c [...]
</div>
<div class="paragraph">
- <p>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.</p>
+ <p>ObjectContext is serializable and does not permanently hold 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.</p>
</div>
</div>
<div class="sect3">
<h4 id="persistent-object-and-its-lifecycle"><a class="anchor"
href="#persistent-object-and-its-lifecycle"></a>2.3.2. Persistent Object and
its Lifecycle</h4>
<div class="paragraph">
- <p>Cayenne can persist Java objects that implement
<code>org.apache.cayenne.Persistent</code> 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.</p>
+ <p>Cayenne can persist Java objects that implement the
<code>org.apache.cayenne.Persistent</code> 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.</p>
</div>
<div class="paragraph">
- <p>Persistent interface provides access to 3 persistence-related
properties - <em>objectId</em>, <em>persistenceState</em> and
<em>objectContext</em>. 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.</p>
+ <p>The <code>Persistent</code> interface provides access to three
persistence-related properties - <em>objectId</em>, <em>persistenceState</em>
and <em>objectContext</em>. All three are initialized by the Cayenne runtime
framework. Your 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 a quick equality check of two objects, knowing
persistence state would allow highlight [...]
</div>
<div class="paragraph">
<p>Each persistent object belongs to a single ObjectContext, and can be
in one of the following persistence states (as defined in
<code>org.apache.cayenne.PersistenceState</code>) :</p>
@@ -561,7 +561,7 @@ ServerRuntime runtime = ServerRuntime.builder()
<td class="tableblock halign-left valign-top"><p class="tableblock">The
object is freshly registered in an ObjectContext, but has not been saved to the
database yet and there is no matching database row.</p></td>
</tr>
<tr>
- <td class="tableblock halign-center valign-middle"><p
class="tableblock"><strong>COMMITED</strong></p></td>
+ <td class="tableblock halign-center valign-middle"><p
class="tableblock"><strong>COMMITTED</strong></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">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.</p></td>
</tr>
<tr>
@@ -570,7 +570,7 @@ ServerRuntime runtime = ServerRuntime.builder()
</tr>
<tr>
<td class="tableblock halign-center valign-middle"><p
class="tableblock"><strong>HOLLOW</strong></p></td>
- <td class="tableblock halign-left valign-top"><p class="tableblock">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.</p></td>
+ <td class="tableblock halign-left valign-top"><p class="tableblock">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
COMMITTED.</p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-middle"><p
class="tableblock"><strong>DELETED</strong></p></td>
@@ -594,7 +594,7 @@ ServerRuntime runtime = ServerRuntime.builder()
<p>We’ll discuss queries in some detail in the <a
href="#queries">Queries</a> chapter. The example above is self-explanatory - we
create a <code>ObjectSelect</code> that matches all <code>Artist</code> objects
present in the database, and then use <code>select</code> to get the
result.</p>
</div>
<div class="paragraph">
- <p>Some queries can be quite complex, returning multiple result sets or
even updating the database. For such queries ObjectContext provides
<code>performGenericQuery()</code> method. While not commonly-used, it is
nevertheless important in some situations. E.g.:</p>
+ <p>Some queries can be quite complex, returning multiple result sets or
even updating the database. For such queries, ObjectContext provides the
<code>performGenericQuery()</code> method. While not commonly used, it is
nevertheless important in some situations. E.g.:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -622,10 +622,10 @@ selectedArtist.setName("Dali");</code></pre>
</div>
</div>
<div class="paragraph">
- <p>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 <code>commitChanges</code> commits
just one object, but generally it can be any number of objects.</p>
+ <p>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, <code>commitChanges</code> commits
just one object, but generally it can be any number of objects.</p>
</div>
<div class="paragraph">
- <p>If instead of commit, we wanted to reset all changed objects to the
previously committed state, we’d call <code>rollbackChanges</code> instead:</p>
+ <p>If, instead of commit, we wanted to reset all changed objects to the
previously committed state, we’d call <code>rollbackChanges</code> instead:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -642,10 +642,10 @@ newArtist.setName("Picasso");</code></pre>
</div>
</div>
<div class="paragraph">
- <p>It will only exist in memory until <code>commitChanges</code> 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
<code>INSERT</code> SQL statement to permanently store the object.</p>
+ <p>It only exists in memory until <code>commitChanges</code> 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
<code>INSERT</code> SQL statement to permanently store the object.</p>
</div>
<div class="paragraph">
- <p><code>deleteObjects</code> method takes one or more Persistent objects
and marks them as <strong>DELETED</strong>:</p>
+ <p>The <code>deleteObjects</code> method takes one or more
<code>Persistent</code> objects and marks them as <strong>DELETED</strong>:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -654,13 +654,13 @@ context.deleteObjects(artist2, artist3,
artist4);</code></pre>
</div>
</div>
<div class="paragraph">
- <p>Additionally <code>deleteObjects</code> 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 <code>commitChanges</code> is called.
Similarly <code>rollbackChanges</code> will undo the effect of
<code>newObject</code> and <code>deleteObjects</code>.</p>
+ <p>Additionally, <code>deleteObjects</code> 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 <code>commitChanges</code> is called.
Similarly <code>rollbackChanges</code> will undo the effect of
<code>newObject</code> and <code>deleteObjects</code>.</p>
</div>
<div class="paragraph">
<p><code>localObject</code> returns a copy of a given persistent object
that is <em>local</em> to a given ObjectContext:</p>
</div>
<div class="paragraph">
- <p>Since an application often works with more than one context,
<code>localObject</code> 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:</p>
+ <p>Since an application often works with more than one context,
<code>localObject</code> 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:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -677,13 +677,13 @@ Artist localArtist =
editingContext.localObject(artist);</code></pre>
</div>
</div>
<div class="paragraph">
- <p>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.</p>
+ <p>Here we discussed the most commonly-used subset of the ObjectContext
API. There are other useful methods, e.g. those allowing you to inspect
registered objects' state in bulk, etc. Check the latest JavaDocs for
details.</p>
</div>
</div>
<div class="sect3">
<h4 id="cayenne-helper-class"><a class="anchor"
href="#cayenne-helper-class"></a>2.3.4. Cayenne Helper Class</h4>
<div class="paragraph">
- <p>There is a useful helper class called <code>Cayenne</code>
(fully-qualified name <code>org.apache.cayenne.Cayenne</code>) 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) :</p>
+ <p>There is a useful helper class called <code>Cayenne</code>
(fully-qualified name <code>org.apache.cayenne.Cayenne</code>) that builds on
the 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) :</p>
</div>
<div class="listingblock">
<div class="content">
@@ -699,25 +699,25 @@ Artist localArtist =
editingContext.localObject(artist);</code></pre>
</div>
</div>
<div class="paragraph">
- <p>For more flexibility, you could use <a
href="#selectbyid">SelectById</a> query instead.</p>
+ <p>For more flexibility, you could use the <a
href="#selectbyid">SelectById</a> query instead.</p>
</div>
<div class="paragraph">
- <p>Feel free to explore <code>Cayenne</code> class API for other useful
methods.</p>
+ <p>Feel free to explore the <code>Cayenne</code> class API for other
useful methods.</p>
</div>
</div>
<div class="sect3">
<h4 id="objectcontext-nesting"><a class="anchor"
href="#objectcontext-nesting"></a>2.3.5. ObjectContext Nesting</h4>
<div class="paragraph">
- <p>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.</p>
+ <p>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 a
child is a nested context and selects or commits its objects via a parent.</p>
</div>
<div class="paragraph">
- <p>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.</p>
+ <p>Nesting is useful to create isolated object editing areas (child
contexts) that all need to 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.</p>
</div>
<div class="paragraph">
- <p>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.</p>
+ <p>In theory, Cayenne supports any number of nesting levels; however,
applications should generally stay with one or two levels, as deep hierarchies
will almost 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.</p>
</div>
<div class="paragraph">
- <p>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.</p>
+ <p>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 detail in the following chapters. Here we concentrate on
the same-VM nesting.</p>
</div>
<div class="paragraph">
<p>To create a nested context, use an instance of ServerRuntime, passing
it the desired parent:</p>
@@ -729,7 +729,7 @@ ObjectContext nested =
runtime.newContext(parent);</code></pre>
</div>
</div>
<div class="paragraph">
- <p>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:</p>
+ <p>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:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -755,13 +755,13 @@ nested.rollbackChanges();</code></pre>
<div class="sect3">
<h4 id="generic-persistent-objects"><a class="anchor"
href="#generic-persistent-objects"></a>2.3.6. Generic Persistent Objects</h4>
<div class="paragraph">
- <p>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.</p>
+ <p>As described in the CayenneModeler chapter, Cayenne supports mapping
of completely generic classes to specific entities. Although for convenience
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.</p>
</div>
<div class="paragraph">
- <p>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.</p>
+ <p>Generic objects are first-class citizens in Cayenne, and all common
persistent operations apply to them as well. There are some peculiarities,
however, described below.</p>
</div>
<div class="paragraph">
- <p>When creating a new generic object, either cast your ObjectContext to
DataContext (that provides <code>newObject(String)</code> API), or provide your
object with an explicit ObjectId:</p>
+ <p>When creating a generic object, either cast your ObjectContext to
DataContext (that provides <code>newObject(String)</code> API), or provide your
object with an explicit ObjectId:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -776,7 +776,7 @@ context.registerNewObject(generic);</code></pre>
</div>
</div>
<div class="paragraph">
- <p>ObjectSelect for a generic object should be created passing entity
name String, instead of just a Java class:</p>
+ <p>ObjectSelect for a generic object should be created by passing the
entity name String, instead of just a Java class:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -793,7 +793,7 @@ generic.writeProperty("name", "New Name");</code></pre>
</div>
</div>
<div class="paragraph">
- <p>This is how an application can obtain entity name of a generic
object:</p>
+ <p>This is how an application can obtain the entity name of a generic
object:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -804,16 +804,16 @@ generic.writeProperty("name", "New Name");</code></pre>
<div class="sect3">
<h4 id="transactions"><a class="anchor" href="#transactions"></a>2.3.7.
Transactions</h4>
<div class="paragraph">
- <p>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 oper [...]
+ <p>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 ope [...]
</div>
<div class="paragraph">
<p>Two cases where transactions need to be taken into consideration are
container- and application-managed transactions.</p>
</div>
<div class="paragraph">
- <p>If you are using Spring, EJB or another environment that manages
transactions, you’ll likely need to switch Cayenne runtime into "external
transactions mode". This is done by setting DI configuration property defined
in <code>Constants.SERVER_EXTERNAL_TX_PROPERTY</code> (see Appendix A). If this
property is set to "true", Cayenne assumes that JDBC Connections obtained by
runtime whenever that might happen are all coming from a transactional
DataSource managed by the container. In [...]
+ <p>If you are using Spring, EJB or another environment that manages
transactions, you’ll likely need to switch the Cayenne runtime into "external
transactions mode". This is done by setting the DI configuration property
defined in <code>Constants.SERVER_EXTERNAL_TX_PROPERTY</code> (see Appendix A).
If this property is set to "true", Cayenne assumes that JDBC Connections
obtained by runtime, whenever that might happen, are all coming from a
transactional DataSource managed by the con [...]
</div>
<div class="paragraph">
- <p>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 via <code>ServerRuntime.performInTransaction</code>
method:</p>
+ <p>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 via the <code>ServerRuntime.performInTransaction</code>
method:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -856,12 +856,12 @@
transactionManager.performInTransaction(transactionalOperation, descriptor);</co
<div class="sect2">
<h3 id="expressions"><a class="anchor" href="#expressions"></a>2.4.
Expressions</h3>
<div class="paragraph">
- <p>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.</p>
+ <p>Cayenne provides a simple, yet powerful, object-based expression
language. The most common uses 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
an API to build expressions in the code and a parser to create expressions from
strings.</p>
</div>
<div class="sect3">
<h4 id="path-expressions"><a class="anchor"
href="#path-expressions"></a>2.4.1. Path Expressions</h4>
<div class="paragraph">
- <p>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 situ [...]
+ <p>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 [...]
</div>
<div class="listingblock">
<div class="content">
@@ -871,7 +871,7 @@
transactionManager.performInTransaction(transactionalOperation, descriptor);</co
<div class="ulist">
<ul>
<li> <p><code>db:</code> is an optional prefix indicating that the
following path is a DB path. Otherwise it is an object path.</p> </li>
- <li> <p><code>segment</code> 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 (".").</p> </li>
+ <li> <p><code>segment</code> is a name of a property (relationship or
attribute in Cayenne terms) in the path. The path must have at least one
segment; segments are separated by dot (".").</p> </li>
<li> <p><code>+</code> An "OUTER JOIN" path component. Currently "+"
only has effect when translated to SQL as OUTER JOIN. When evaluating
expressions in memory, it is ignored.</p> </li>
</ul>
</div>
@@ -890,12 +890,12 @@
transactionManager.performInTransaction(transactionalOperation, descriptor);</co
</div>
<div class="ulist">
<ul>
- <li> <p><code>db:NAME</code> - can be used to navigate to the value of
"NAME" column of some unspecified table.</p> </li>
+ <li> <p><code>db:NAME</code> - can be used to navigate to a value in the
"NAME" column of some unspecified table.</p> </li>
<li> <p><code>db:artist.artistExhibits.exhibit.CLOSING_DATE</code> - can
be used to match a closing date of any of the exhibits of a related artist
record.</p> </li>
</ul>
</div>
<div class="paragraph">
- <p>Cayenne supports "aliases" in path Expressions. E.g. the same
expression can be written using explicit path or an alias:</p>
+ <p>Cayenne supports "aliases" in path expressions. E.g. the same
expression can be written using the explicit path or an alias:</p>
</div>
<div class="ulist">
<ul>
@@ -904,13 +904,13 @@
transactionManager.performInTransaction(transactionalOperation, descriptor);</co
</ul>
</div>
<div class="paragraph">
- <p>SelectQuery using the second form of the path expression must be made
aware of the alias via <code>SelectQuery.aliasPathSplits(..)</code>, 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.</p>
+ <p>SelectQuery using the second form of the path expression must be made
aware of the alias via <code>SelectQuery.aliasPathSplits(..)</code>; otherwise,
an <code>Exception</code> 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 <code>Expression</code>. Each alias for any given
path would result in a separate join. Without aliases, a single join will be
used for a group of matc [...]
</div>
</div>
<div class="sect3">
<h4 id="creating-expressions-from-strings"><a class="anchor"
href="#creating-expressions-from-strings"></a>2.4.2. Creating Expressions from
Strings</h4>
<div class="paragraph">
- <p>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
<code>ExpressionFactory.exp</code> static method. Here is an example:</p>
+ <p>While in most cases users are likely to rely on the API from the
following section for expression creation, we’ll start by showing String
expressions, as this will help you understand the semantics. A Cayenne
expression can be represented as a String, which can be converted to an
expression object using the <code>ExpressionFactory.exp</code> static method.
Here is an example:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -919,7 +919,7 @@ Expression exp =
ExpressionFactory.exp(expString);</code></pre>
</div>
</div>
<div class="paragraph">
- <p>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 u [...]
+ <p>This particular expression may be used to match Paintings whose names
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 say that this
expression "may be used to matc [...]
</div>
<div class="paragraph">
<p>Character constants that are not paths or numeric values should be
enclosed in single or double quotes. Two of the expressions below are
equivalent:</p>
@@ -953,7 +953,7 @@ name LIKEIGNORECASE 'A%'</code></pre>
</div>
</div>
<div class="paragraph">
- <p>Path prefixes. Object expressions are unquoted strings, optionally
prefixed by <code>obj:</code> (usually they are not prefixed at all actually).
Database expressions are always prefixed with <code>db:</code>. A special kind
of prefix, not discussed yet is <code>enum:</code> that prefixes an enumeration
constant:</p>
+ <p>Path prefixes. Object expressions are unquoted strings, optionally
prefixed by <code>obj:</code> (usually they are not prefixed at all). Database
expressions are always prefixed with <code>db:</code>. A special kind of
prefix, not discussed yet, is <code>enum:</code> that prefixes an enumeration
constant:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -974,7 +974,7 @@ name = enum:org.foo.EnumClass.VALUE1</code></pre>
</div>
</div>
<div class="paragraph">
- <p>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:</p>
+ <p>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:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -982,7 +982,7 @@ name = enum:org.foo.EnumClass.VALUE1</code></pre>
</div>
</div>
<div class="paragraph">
- <p>Parameters. Expressions can contain named parameters (names that start
with "$") that can be substituted with values either by name or by position.
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 the examples of
both positional and named [...]
+ <p>Parameters. Expressions can contain named parameters (names that start
with "$") that can be substituted with values either by name or by position.
Parameterized expressions let you 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 the
expression is the only way to represent it as String. Here are examples of both
positional and named para [...]
</div>
<div class="listingblock">
<div class="content">
@@ -1005,7 +1005,7 @@ Expression qualifier2 =
template.paramsArray("Monet");</code></pre>
</div>
</div>
<div class="paragraph">
- <p>In parameterized expressions with LIKE clause, SQL wildcards must be
part of the values in the Map and not the expression string itself:</p>
+ <p>In parameterized expressions with a LIKE clause, SQL wildcards must be
part of the values in the Map and not the expression string itself:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -1017,12 +1017,12 @@ Expression qualifier2 =
template.paramsArray("Monet");</code></pre>
</div>
<div class="listingblock">
<div class="content">
- <pre class="highlight"><code class="language-java java"
data-lang="java">Artist dali = ... // asume we fetched this one already
+ <pre class="highlight"><code class="language-java java"
data-lang="java">Artist dali = ... // assume we fetched this one already
Expression qualifier = ExpressionFactory.exp("artist = $artist",
dali);</code></pre>
</div>
</div>
<div class="paragraph">
- <p>When using positional binding, Cayenne would expect values for all
parameters to be present. Binding by name offers extra flexibility:
subexpressions with uninitialized parameters are automatically pruned from the
expression. So e.g. if certain parts of the expression criteria are not
provided to the application, you can still build a valid expression:</p>
+ <p>When you use positional binding, Cayenne expects values for all
parameters to be present. Binding by name offers extra flexibility:
sub-expressions with uninitialized parameters are automatically pruned from the
expression. So, e.g., if certain parts of the expression criteria are not
provided to the application, you can still build a valid expression</p>
</div>
<div class="listingblock">
<div class="content">
@@ -1037,13 +1037,13 @@ Expression qualifier1 = template.params(p1);
</div>
</div>
<div class="paragraph">
- <p>Null handling. Handling of Java nulls as operands is no different from
normal values. Instead of using special conditional operators, like SQL does
(<code>IS NULL</code>, <code>IS NOT NULL</code>), "=" and "!=" expressions are
used directly with null values. It is up to Cayenne to translate expressions
with nulls to the valid SQL.</p>
+ <p>Null handling. Handling of Java nulls as operands is no different
handling from normal values. Instead of using special conditional operators,
like SQL does (<code>IS NULL</code>, <code>IS NOT NULL</code>), "=" and "!="
expressions are used directly with null values. It is up to Cayenne to
translate expressions with nulls to the valid SQL.</p>
</div>
</div>
<div class="sect3">
<h4 id="creating-expressions-via-api"><a class="anchor"
href="#creating-expressions-via-api"></a>2.4.3. Creating Expressions via
API</h4>
<div class="paragraph">
- <p>Creating expressions from Strings is a powerful and dynamic approach,
however a safer alternative is to use Java API. It provides compile-time
checking of expressions validity. The API in question is provided by
<code>ExpressionFactory</code> class (that we’ve seen already), Property class
and Expression class itself. <code>ExpressionFactory</code> contains a number
of self-explanatory static methods that can be used to build expressions.
E.g.:</p>
+ <p>Creating expressions from Strings is a powerful and dynamic approach,
however a safer alternative is to use the Java API. It provides compile-time
checking of the expression’s validity. The API in question is provided by the
<code>ExpressionFactory</code> class (that we’ve seen already), the Property
class and the Expression class itself. <code>ExpressionFactory</code> contains
a number of self-explanatory static methods that can be used to build
expressions. E.g.:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -1058,13 +1058,13 @@ Expression finalExp = e1.andExp(e2);</code></pre>
<tbody>
<tr>
<td class="icon"> <i class="fa fa-info-circle fa-2x" title="Note"></i>
</td>
- <td class="content"> The last line in the example above shows how to
create a new expression by "chaining" two other expressions. 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. </td>
+ <td class="content"> The last line in the example above shows how to
create a new expression by "chaining" two other expressions. 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.
Expression API treats existing expressions as immutable. </td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph">
- <p>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:</p>
+ <p>As discussed earlier, Cayenne supports aliases in path Expressions, so
you can control how SQL joins are generated if the same path is encountered
more than once in the same Expression. Two ExpressionFactory methods let you
implicitly generate aliases to "split" match paths into individual joins if
needed:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -1073,29 +1073,29 @@ Expression matchAllExp(String path, Object...
values)</code></pre>
</div>
</div>
<div class="paragraph">
- <p>"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. <code>"|exhibits.paintings"</code>,
<code>"exhibits|paintings"</code>, etc. Internally Cayenne would generate
distinct aliases for each of the split expressions, [...]
+ <p>The "Path" argument to both of these methods can use a split character
(a pipe symbol '|') instead of a dot to indicate that the 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. The
split must always precede a relationship. E.g.
<code>"|exhibits.paintings"</code>, <code>"exhibits|paintings"</code>, etc.
Internally, Cayenne generates distinct aliases for each of the split ex [...]
</div>
<div class="paragraph">
- <p>While ExpressionFactory is pretty powerful, there’s an even easier way
to create expression using static Property objects generated by Cayenne for
each persistent class. Some examples:</p>
+ <p>While ExpressionFactory is pretty powerful, there’s an even easier way
to create an expression using static Property objects generated by Cayenne for
each persistent class. Some examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java"
data-lang="java">// Artist.NAME is generated by Cayenne and has a type of
Property<String>
Expression e1 = Artist.NAME.eq("Pablo");
-// Chaining multiple properties into a path..
+// Chaining multiple properties into a path.
// Painting.ARTIST is generated by Cayenne and has a type of
Property<Artist>
Expression e2 = Painting.ARTIST.dot(Artist.NAME).eq("Pablo");</code></pre>
</div>
</div>
<div class="paragraph">
- <p>Property objects provide the API mostly analogius to
ExpressionFactory, though it is significantly shorter and is aware of the value
types. It provides compile-time checks of both property names and types of
arguments in conditions. We will use Property-based API in further
examples.</p>
+ <p>Property objects provide the API mostly analogous to
ExpressionFactory, though it is significantly shorter and is aware of the value
types. It provides compile-time checks of both property names and types of
arguments in conditions. We will use Property-based API in further
examples.</p>
</div>
</div>
<div class="sect3">
<h4 id="evaluate"><a class="anchor" href="#evaluate"></a>2.4.4. Evaluating
Expressions in Memory</h4>
<div class="paragraph">
- <p>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.</p>
+ <p>When used in a query, an expression is converted to a SQL WHERE 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, and
in-memory filtering.</p>
</div>
<div class="paragraph">
<p>Checking whether an object satisfies an expression:</p>
@@ -1981,12 +1981,12 @@ List<String> names =
context.performQuery(query);</code></pre>
<p>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 ob [...]
</div>
<div class="paragraph">
- <p>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.</p>
+ <p>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 environment 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.</p>
</div>
<div class="sect3">
<h4 id="types-of-lifecycle-events"><a class="anchor"
href="#types-of-lifecycle-events"></a>2.7.1. Types of Lifecycle Events</h4>
<div class="paragraph">
- <p>Cayenne defines the following 8 types of lifecycle events for which
callbacks can be regsitered:</p>
+ <p>Cayenne defines the following 8 types of lifecycle events for which
callbacks can be registered:</p>
</div>
<table id="lifecycleEvent" class="tableblock frame-all grid-all stretch
table table-bordered">
<caption class="title">
@@ -2078,7 +2078,7 @@ public class Order extends _Order {
<tbody>
<tr>
<td class="icon"> <i class="fa fa-info-circle fa-2x" title="Note"></i>
</td>
- <td class="content"> Validation and callbacks: There is a clear
overlap in functionality between object callbacks and
<code>DataObject.validateForX()</code> 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. </td>
+ <td class="content"> Validation and callbacks: There is a clear
overlap in functionality between object callbacks and
<code>DataObject.validateForX()</code> methods. In the future validation may be
completely superseded 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. </td>
</tr>
</tbody>
</table>
@@ -2164,7 +2164,7 @@ void postRemove(Persistent object) {
</div>
<div class="listingblock">
<div class="content">
- <pre class="highlight"><code class="language-Java Java"
data-lang="Java">// similar example with multipe annotations on a single method
+ <pre class="highlight"><code class="language-Java Java"
data-lang="Java">// similar example with multiple annotations on a single method
// each matching just one entity
@PostPersist(MyEntity1.class)
@PostRemove(MyEntity1.class)
@@ -2359,7 +2359,7 @@
PrefetchTreeNode.DISJOINT_BY_ID_PREFETCH_SEMANTICS</code></pre>
<p><code><a href="#select">ObjectSelect</a></code> query supports all
three types of semantics. You can mix and match them in the same query for
different prefetches.</p>
</div>
<div class="paragraph">
- <p><code><a href="#sqlselect">SQLSelect</a></code> query supports "JOINT"
and "DISJOINT_BY_ID". It does not work with "DISJOINT", as the query does not
provide enough information to Cayenne to build dependent prefetch queries. So
"DISJOINT" will result in exception. "JOINT" prefetching requires a bit of
effort shaping the SQL to include the right columns in the result and label
them properly to be convertable into object properties. The main rules to
follow are:</p>
+ <p><code><a href="#sqlselect">SQLSelect</a></code> query supports "JOINT"
and "DISJOINT_BY_ID". It does not work with "DISJOINT", as the query does not
provide enough information to Cayenne to build dependent prefetch queries. So
"DISJOINT" will result in exception. "JOINT" prefetching requires a bit of
effort shaping the SQL to include the right columns in the result and label
them properly to be convertible into object properties. The main rules to
follow are:</p>
</div>
<div class="ulist">
<ul>
@@ -2402,7 +2402,7 @@
PrefetchTreeNode.DISJOINT_BY_ID_PREFETCH_SEMANTICS</code></pre>
<p>Converting result set data to Persistent objects and registering these
objects in the ObjectContext can be an expensive operation comparable to the
time spent running the query (and frequently exceeding it). Internally Cayenne
builds the result as a list of DataRows, that are later converted to objects.
Skipping the last step and using data in the form of DataRows can significantly
increase performance.</p>
</div>
<div class="paragraph">
- <p>DataRow is a simply a map of values keyed by their DB column name. It
is a ubiqutous representation of DB data used internally by Cayenne. And it can
be quite usable as is in the application in many cases. So performance
sensitive selects should consider DataRows - it saves memory and CPU cycles.
All selecting queries support DataRows option, e.g.:</p>
+ <p>DataRow is a simply a map of values keyed by their DB column name. It
is a ubiquitous representation of DB data used internally by Cayenne. And it
can be quite usable as is in the application in many cases. So performance
sensitive selects should consider DataRows - it saves memory and CPU cycles.
All selecting queries support DataRows option, e.g.:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -2635,7 +2635,7 @@ context.performGenericQuery(refresh);</code></pre>
<div class="sect4">
<h5 id="di-bindings-api"><a class="anchor"
href="#di-bindings-api"></a>2.9.1.1. DI Bindings API</h5>
<div class="paragraph">
- <p>To have a working DI container, we need three things: service
interfaces and classes, a module that describes service bindings, a container
that loads the module, and resolves the depedencies. Let’s start with service
interfaces and classes:</p>
+ <p>To have a working DI container, we need three things: service
interfaces and classes, a module that describes service bindings, a container
that loads the module, and resolves the dependencies. Let’s start with service
interfaces and classes:</p>
</div>
<div class="listingblock">
<div class="content">
@@ -2766,7 +2766,7 @@ binder.bind(Key.get(Service2.class,
"i2")).to(Service2Impl.class);</code></pre>
</div>
</div>
<div class="paragraph">
- <p>Another types of confiuguration that can be bound in the container
are lists and maps. They will be discussed in the following chapters.</p>
+ <p>Another types of configuration that can be bound in the container are
lists and maps. They will be discussed in the following chapters.</p>
</div>
</div>
<div class="sect4">
@@ -2792,7 +2792,7 @@ binder.bind(Key.get(Service2.class,
"i2")).to(Service2Impl.class);</code></pre>
<div class="sect4">
<h5 id="overriding-services"><a class="anchor"
href="#overriding-services"></a>2.9.1.3. Overriding Services</h5>
<div class="paragraph">
- <p>Cayenne DI allows to override services already definied in the
current module, or more commonly - some other module in the the same container.
Actually there’s no special API to override a service, you’d just bind the
service key again with a new implementation or provider. The last binding for a
key takes precedence. This means that the order of modules is important when
configuring a container. The built-in Cayenne injector ensures that Cayenne
standard modules are loaded firs [...]
+ <p>Cayenne DI allows to override services already defined in the current
module, or more commonly - some other module in the the same container.
Actually there’s no special API to override a service, you’d just bind the
service key again with a new implementation or provider. The last binding for a
key takes precedence. This means that the order of modules is important when
configuring a container. The built-in Cayenne injector ensures that Cayenne
standard modules are loaded first [...]
</div>
</div>
</div>
@@ -2833,7 +2833,7 @@ ServerRuntime runtime = ServerRuntime.builder()
</div>
</div>
<div class="paragraph">
- <p>A second one is to contribute a property to
<code>o.a.c.configuration.DefaultRuntimeProperties.properties</code> map (see
the next section on how to do that). This map contains the default property
values and can accept application-specific values, overrding the defaults.</p>
+ <p>A second one is to contribute a property to
<code>o.a.c.configuration.DefaultRuntimeProperties.properties</code> map (see
the next section on how to do that). This map contains the default property
values and can accept application-specific values, overriding the defaults.</p>
</div>
<div class="paragraph">
<p>Note that if a property value is a name of a Java class, when this
Java class is instantiated by Cayenne, the container performs injection of
instance variables. So even the dynamically specified Java classes can use
@Inject annotation to get a hold of other Cayenne services.</p>
@@ -2851,7 +2851,7 @@ ServerRuntime runtime = ServerRuntime.builder()
<div class="content">
<pre class="highlight"><code class="language-Java Java"
data-lang="Java">public class MyDbAdapterDetector implements DbAdapterDetector {
public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
- // check if we support this database and retun custom adapter
+ // check if we support this database and return custom adapter
...
}
}</code></pre>
@@ -3104,7 +3104,7 @@ ServerRuntime runtime = ServerRuntime.builder()
<div class="ulist">
<ul>
<li> <p>A SQL migrations framework is used to bring a local DB to a
certain version. This is outside of the scope of Cayenne and is done with a
third-party tool, such as Liquibase or Flyway.</p> </li>
- <li> <p>OR mapping model (Cayenne XML files) are synchronized with the
state of the database using <code>"cdbimport"</code> tool provdied by
Cayenne.</p> </li>
+ <li> <p>OR mapping model (Cayenne XML files) are synchronized with the
state of the database using <code>"cdbimport"</code> tool provided by
Cayenne.</p> </li>
<li> <p>Object layer of the OR mapping model is customized to the
developer liking, usually via CayenneModeler. Subsequent runs of
<code>"cdbimport"</code> will not override any customizations that you
make.</p> </li>
<li> <p>Java classes are generated using <code>"cgen"</code> tool
provided by Cayenne.</p> </li>
</ul>
@@ -3253,7 +3253,7 @@ ServerRuntime runtime = ServerRuntime.builder()
</div>
</div>
<div class="paragraph">
- <p>In the example above, Cayenne reverse engineering process contains
three catalogs named as shop_01, shop_02 and shop_03, each of wich has their
own schemas. Cayenne will load all data only from the declared catalogs and
schemas.</p>
+ <p>In the example above, Cayenne reverse engineering process contains
three catalogs named as shop_01, shop_02 and shop_03, each of which has their
own schemas. Cayenne will load all data only from the declared catalogs and
schemas.</p>
</div>
<div class="paragraph">
<p>If you want to load everything from database, you could simply declare
catalog specification alone.</p>
@@ -3636,7 +3636,7 @@ ServerRuntime runtime = ServerRuntime.builder()
<div class="sect2">
<h3 id="re-modeler"><a class="anchor" href="#re-modeler"></a>3.4. Reverse
Engineering in Cayenne Modeler</h3>
<div class="paragraph">
- <p>Alternative aproach to using <a href="#cdbimport">cdbimport</a> is
doing reverse engineering from <a href="#cayenne-modeler">CayenneModeler</a>.
Currently modeler GUI doesn’t support all features of ant/maven tasks but it
suffice for general DB import. Especially it’s a good place to quickly start
working on your data model.</p>
+ <p>Alternative approach to using <a href="#cdbimport">cdbimport</a> is
doing reverse engineering from <a href="#cayenne-modeler">CayenneModeler</a>.
Currently modeler GUI doesn’t support all features of ant/maven tasks but it
suffice for general DB import. Especially it’s a good place to quickly start
working on your data model.</p>
</div>
<div class="paragraph">
<p>You can find reverse engineering tool in dataMap view on
<strong>DbImport Tab</strong>.</p>
@@ -4038,7 +4038,7 @@ public class MyEntity extends _MyEntity {
</div>
</div>
<div class="paragraph">
- <p>Also JCache module supports contribution of preconfigured cache
manager.</p>
+ <p>Also JCache module supports contribution of pre-configured cache
manager.</p>
</div>
<div class="listingblock">
<div class="content">