Return-Path: Delivered-To: apmail-cayenne-commits-archive@www.apache.org Received: (qmail 67737 invoked from network); 20 Feb 2011 17:21:28 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 20 Feb 2011 17:21:28 -0000 Received: (qmail 66376 invoked by uid 500); 20 Feb 2011 17:21:28 -0000 Delivered-To: apmail-cayenne-commits-archive@cayenne.apache.org Received: (qmail 66342 invoked by uid 500); 20 Feb 2011 17:21:27 -0000 Mailing-List: contact commits-help@cayenne.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cayenne.apache.org Delivered-To: mailing list commits@cayenne.apache.org Received: (qmail 66334 invoked by uid 99); 20 Feb 2011 17:21:26 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 20 Feb 2011 17:21:26 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 20 Feb 2011 17:21:23 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id ED0F32388A39; Sun, 20 Feb 2011 17:21:02 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1072639 - in /cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation: Cayenne Guide/Caching and Fresh Data/Query Result Caching/ Cayenne Guide/Customization/Extended Types/ Cayenne Guide/DataContext/Obtaining DataContext/ Cayenne... Date: Sun, 20 Feb 2011 17:21:02 -0000 To: commits@cayenne.apache.org From: aadamchik@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110220172102.ED0F32388A39@eris.apache.org> Author: aadamchik Date: Sun Feb 20 17:21:02 2011 New Revision: 1072639 URL: http://svn.apache.org/viewvc?rev=1072639&view=rev Log: refreshing 3.1 docs from wiki Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Caching and Fresh Data/Query Result Caching/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Customization/Extended Types/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/DataContext/Obtaining DataContext/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Queries/Caching Query Results/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Stored Procedures/Executing a Stored Procedure/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Delete/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Java Classes/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Object Relational Mapping/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Setup/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Starting Project/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Webapp/index.html cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Overview/Guide to 3.1 Features/index.html Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Caching and Fresh Data/Query Result Caching/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Caching%20and%20Fresh%20Data/Query%20Result%20Caching/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Caching and Fresh Data/Query Result Caching/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Caching and Fresh Data/Query Result Caching/index.html Sun Feb 20 17:21:02 2011 @@ -146,17 +146,17 @@ cayenne.group.artists.cron = 10 1 * * *
cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JMSBroadcastingListener
-# other JMS paramaters go here...
+# other JMS parameters go here...
cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JavaGroupsBroadcastingListener
-# other JavaGroups paramaters go here...
+# other JavaGroups parameters go here...

Query Cache Conclusions

-

The consequence of consistently using caching strategies and coming up with reasonable set of ache groups is that many applications no longer has to cache fetched lists explicitly. Re-running a query with a one of the caching strategies (especially with "LOCAL_CACHE") becomes an extremely fast operation. Also the code becomes cleaner, as the state is stored in Cayenne, not in the application code. One possible exception from this rule is when the application needs to access the same list between requests, regardless of whether it is stale or not.

+

The consequence of consistently using caching strategies and coming up with a reasonable set of cache groups is that applications no longer have to cache fetched lists explicitly. Re-running a query with a one of the caching strategies (especially with "LOCAL_CACHE") becomes an extremely fast operation. Also the code becomes cleaner, as the state is stored in Cayenne, not in the application code. One possible exception from this rule is when an application needs to access the same list between requests, regardless of whether it is stale or not.

Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Customization/Extended Types/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Customization/Extended%20Types/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Customization/Extended Types/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Customization/Extended Types/index.html Sun Feb 20 17:21:02 2011 @@ -55,11 +55,11 @@ -

JDBC specification defines a set of "standard" database column types (defined in java.sql.Types class) and a very specific mapping of these types to Java Object Types, such as java.lang.String, java.math.BigDecimal, etc. Sometimes there is a need to use a custom Java type not known to JDBC driver. CayenneModeler allows to configure an arbitrary Java class as an org.apache.cayenne.map.ObjAttribute type by simply entering a fully-qualified name such class in the type column of an ObjAttribute. However there is more to it than just that. Cayenne needs to know how to instantiate this type from a database "primitive" value, and conversly, how to transform an object of the custom type to a JDBC-compatible object.

+

JDBC specification defines a set of "standard" database column types (defined in java.sql.Types class) and a very specific mapping of these types to Java Object Types, such as java.lang.String, java.math.BigDecimal, etc. Sometimes there is a need to use a custom Java type not known to JDBC driver. CayenneModeler allows to configure an arbitrary Java class as an org.apache.cayenne.map.ObjAttribute type by simply entering a fully-qualified name such class in the type column of an ObjAttribute. However there is more to it than just that. Cayenne needs to know how to instantiate this type from a database "primitive" value, and conversely, how to transform an object of the custom type to a JDBC-compatible object.

Supporting Non-Standard Types

-

org.apache.cayenne.access.types.ExtendedType interface serves to integrate a custom attribute type to Cayenne. An implementation must provide ExtendedType.getClassName() method that returns a fully qualified Java class name for the supported custom type, and a number of methods that convert data between JDBC and custom type. Installing an ExtendedType currently has to be done in the code, some time during Cayenne startup (modeler support will be added in the future). The following code sample demonstrates this procedure:

+

org.apache.cayenne.access.types.ExtendedType interface serves to integrate a custom attribute type to Cayenne. An implementation must provide ExtendedType.getClassName() method that returns a fully qualified Java class name for the supported custom type, and a number of methods that convert data between JDBC and custom type. Configuring an ExtendedType is has in the code, some time during Cayenne startup. The following code sample demonstrates this procedure:

// create custom ExtendedType instance
 ExtendedType customType = new MyCustomType();
@@ -70,15 +70,14 @@
 DataNode node = domain.getNode("node_name");
 
 // install ExtendedType
-node.getAdapter().getExtendedTypes().registerType(customType);
-
+node.getAdapter().getExtendedTypes().registerType(customType);

DbAdapters and Extended Types

-

As shown in the example above, ExtendedTypes are stored by DbAdapter. In fact DbAdapters often install their own extended types to address incompatibilities, incompletness and differences between JDBC drivers in handling "standard" JDBC types. For instance some drivers support reading large character columns (CLOB) as java.sql.Clob, but some other - as "character stream", etc. Adapters provided with Cayenne override configureExtendedTypes() method to install their own types, possibly substituting Cayenne defaults. Custom DbAdapters can use the same technique.

+

As shown in the example above, ExtendedTypes are stored by DbAdapter. In fact DbAdapters often install their own extended types to address incompatibilities, incompleteness and differences between JDBC drivers in handling "standard" JDBC types. For instance some drivers support reading large character columns (CLOB) as java.sql.Clob, but some other - as "character stream", etc. Adapters provided with Cayenne override configureExtendedTypes() method to install their own types, possibly substituting Cayenne defaults. Custom DbAdapters can use the same technique.

-

Three tier considerations

+

ROP Considerations

If you are using Cayenne in a three tier (ROP) environment, serialization of the extended type becomes important. More information can be found here.

Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/DataContext/Obtaining DataContext/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/DataContext/Obtaining%20DataContext/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/DataContext/Obtaining DataContext/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/DataContext/Obtaining DataContext/index.html Sun Feb 20 17:21:02 2011 @@ -59,82 +59,43 @@
  • Customization
  • -
    TODO... The API below looks different in 3.1
    +

    Depending on deployment environment and application needs, Cayenne can be configured in a few different ways to make DataContext instances available. This is discussed in detail in deployment chapter. But basically it comes down to getting a hold of an instance of ServerRuntime and calling getContext() on it as described below.

    -

    Depending on deployment environment and application needs, Cayenne can be configured in a few different ways to make DataContext instances available. This is discussed in detail in deployment chapter. In this chapter we assume a properly deployed application and will concentrate on how to obtain a DataContext for the database access. The following are the most common ways to achieve that:

    - -

    Creating DataContext on the Spot

    - -

    A new DataContext instance normally can be created using the following code:

    +

    Obtaining a DataContext from the DI Runtime

    -
    import org.apache.cayenne.access.DataContext;
    -...
    -DataContext context = DataContext.createDataContext();
    +
    ServerRuntime runtime = ...
    +ObjectContext context = runtime.getContext()
    -

    This approach may be used in standalone applications, where the notion of a "session" is user-defined. In web applications the correct instance of DataContext is usually bound to a session or a request thread externally, and all that is needed is to retrieve it, as discussed below. Creating a new DataContext for each request is not a recommended practice.

    - -

    Retrieving Session-Bound DataContext in Web Applications

    - -

    A web application can be configured to automatically create a new instance of DataContext for each new HttpSession, and set it as a session attribute. Retrieving it from a session is done with the following code:

    +

    Note that every call to getContext() returns a new instance. Also note that it returns ObjectContext (an interface implemented by DataContext). If you need to use DataContext API not declared in ObjectContext, you may use a cast:

    -
    import org.apache.cayenne.conf.ServletUtil;
    -import org.apache.cayenne.access.DataContext;
    -...
    -
    -// assume this exists
    -HttpSession session;
    -DataContext context = ServletUtil.getSessionContext(session);
    +
    ServerRuntime runtime = ...
    +DataContext context = (DataContext) runtime.getContext()
    +

    But if you don't, we recommend to stick with ObjectContext in your code, as it makes the code more flexible and portable to the future versions of Cayenne.

    -

    Retrieving Thread-Bound DataContext.

    +

    Retrieving Thread-Bound DataContext

    -

    An application can bind a DataContext to a current execution thread. Later on the code that needs DB access can retrieve this DataContext without making any assumptions about the environment. This approach is universal and works in all types of applications (web, standalone, etc.). Previously bound DataContext can be retrieved by calling DataContext.getThreadDataContext() static method. If no DataContext was bound to the current thread, this method throws IllegalStateException:

    +

    An application can bind a context to a current execution thread (e.g. via CayenneFilter or manually). Later on the code that needs DB access can retrieve this DataContext without making any assumptions about the environment. This approach is universal and works in all types of applications (web, standalone, etc.). Previously bound context can be retrieved by calling BaseContext.getThreadObjectContext() static method. If no context was bound to the current thread, this method throws IllegalStateException (same rules for casting ObjectContext to DataContext as above apply) :

    -
    import org.apache.cayenne.access.DataContext;
    -...
    -// we are positive there is DataContext in the current thread, and do not want
    +
    // we are positive there is DataContext in the current thread, and do not want
     // to handle possible exception...
    -DataContext context = DataContext.getThreadDataContext();
    -
    +
    DataContext context = (DataContext) BaseContext.getThreadObjectContext();
    -
    -
    import org.apache.cayenne.access.DataContext;
    -...
    -// we want to handle the condition of no thread context...
    +
    // we want to handle the condition of no thread-bound context...
     try {
    -    DataContext context = DataContext.getThreadDataContext();
    +    DataContext context = (DataContext) BaseContext.getThreadObjectContext();
     }
     catch(IllegalStateException ex) {
         // handle failure
         ....
     }
    -
    - - -

    Multiple DataDomains (Advanced)

    - -

    Cayenne can be configured to support mass database hosting. This is a so-called Application Service Provider (ASP) scenario. Basic architecture of such setup is a single application supporting multiple databases (or more generally - data sources), each one with same or similar schema. Each data source corresponds to an individual ASP "customer" using the system. Each customer has a number of users that will log in to the system and are only allowed to view data from their data source.

    - -

    This approach, though not required for most normal applications, could be quiet common and powerful in some enterprise systems. To implement it, each DataContext must be limited to access only a relevant subset of datasources.

    - -

    Considering that behind the scenes a source of DataContext instances is an object called DataDomain, Cayenne allows creation of multiple DataDomains per project. Each DataDomain would support a single "customer". Creation of DataContext in this case is done using DataDomain name as a parameter:

    - -
    -
    import org.apache.cayenne.access.DataContext;
    -...
    -
    -// domain name string is initialized depending on
    -// the application logic. For instance it can be based
    -// on the logged in user's company, etc.
    -String domainName = ...;
    -DataContext context = DataContext.createDataContext(domainName);
    .
    Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Queries/Caching Query Results/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Queries/Caching%20Query%20Results/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Queries/Caching Query Results/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Queries/Caching Query Results/index.html Sun Feb 20 17:21:02 2011 @@ -61,11 +61,7 @@
  • Customization
  • -

    Cayenne provides a way to cache query results, avoiding unneeded database trips for the frequently used queries. Caching policy is configured per query. Policy can be set via the API or in CayenneModeler.

    - -
    Upgrading to Cayenne 1.2 and Newer
    org.apache.cayenne.query.GenericSelectQuery interface that defined cache policy types is deprecated. Cache policies are now a part of the new org.apache.cayenne.query.QueryMetadata interface.
    - -

    The following cache policies are supported:

    +

    Cayenne provides a way to cache query results, avoiding unneeded database trips for the frequently used queries. Caching strategy is configured per query. A strategy can be set via API or in CayenneModeler. Possible strategies, as defined in the org.apache.cayenne.query.QueryCacheStrategy enum are the following:

    @@ -75,29 +71,29 @@ - + - - + + - - - + + + - + - + - +
    Cache Behavior
    (default policy) QueryMetadata.NO_CACHE (default) NO_CACHE N/A Always fetch, never use cache, never save to cache
    QueryMetadata.LOCAL_CACHEDataContextLOCAL_CACHEObjectContext If result is previously cached, use it, otherwise do a fetch and store result in cache for future use
    QueryMetadata.LOCAL_CACHE_REFRESHDataContextNever use cache, alwyas do a fetch and store result in cache for future useLOCAL_CACHE_REFRESHObjectContextNever use cache, always do a fetch and store result in cache for future use
    QueryMetadata.SHARED_CACHESHARED_CACHE DataDomain (usually shared by all contexts in the same JVM) If result is previously cached, use it, otherwise do a fetch and store result in cache for future use
    QueryMetadata.SHARED_CACHE_REFRESHSHARED_CACHE_REFRESH DataDomain (usually shared by all contexts in the same JVM)Never use cache, alwyas do a fetch and store result in cache for future useNever use cache, always do a fetch and store result in cache for future use
    @@ -105,86 +101,57 @@

    It is important to understand that caching of result lists is done independently from caching of individual DataObjects and DataRows. Therefore the API is different as well. Also cached results lists are not synchronized across VMs (even the shared cache).

    -

    API for Result Caching

    -

    Users must set two Query parameters to configure caching - query name that is used as a key to result cache and query cache policy (one of the policies above). Note that if two unrelated queries have the same name, they will hit the same cache entry. This is not a bug, this is a feature that should be taken into consideration when naming queries.

    +

    When creating queries in the code, users may set a desired cache strategy per query. Below we will create a query and set its caching policy to LOCAL_CACHE:

    -

    Below we will create a query and set its caching policy to LOCAL_CACHE:

    SelectQuery query = new SelectQuery(Artist.class);
     
    -// set query name that will be used as a unique key to perform result caching
    -query.setName("MySelect");
    -
    -// set local cache policy, meaning the cache will be stored in the DataContext 
    +// set local cache strategy, meaning the cache will be stored in the ObjectContext 
     // and not shared between different contexts
    -query.setCachePolicy(GenericSelectQuery.LOCAL_CACHE);
    +query.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
     
    -DataContext context = ... // assume this exists
    +ObjectContext context = ... // assume this exists
     
    -// there is probably no cache at this point, so the query will hit the database
    +// if there was no cache at this point, the query will hit the database, 
    +// and will store the result in the cache
     List objects = context.performQuery(query);
     
    -

    Reruning the query in the same DataContext at a later time will be much faster as it will be hitting the cache:

    +

    Now if we rerun the same query (or create a new instance of the query with the same set of parameters), we'll get cached result, which will be much faster than fetching it from DB.

    -
    -
    List objects1 = context.performQuery(query);
    -
    -
    +

    The point about 2 separate queries reusing the same cache entry is worth repeating. A cache key for each query is automatically generated by Cayenne based on the type of the query and its parameters (such as qualifier, ordering, etc.). So a query itself does not need to be cached by the user code for future reuse. New queries can be created as needed.

    -

    Here we want to refresh the cache, but still keep caching the fresh result:

    -
    query.setCachePolicy(GenericSelectQuery.LOCAL_CACHE_REFRESH);
    +
    // creating a new query, same as the previous one
    +SelectQuery query1 = new SelectQuery(Artist.class);
     
    -List objects2 = context.performQuery(query);
    +// this will hit the local cache
    +List objects1 = context.performQuery(query1);
     
    -

    The example above shows caching with SelectQuery, but it works exactly the same way for SQLTemplate and ProcedureQuery. Similarly SHARED_CACHE and SHARED_CACHE_REFRESH cache policies create cache shared by all DataDontexts that work with a given DataDomain.

    - - -
    Upgrading to Cayenne 1.2 and Newer
    Cache refreshing API has changed in 1.2. Cayenne 1.1 relied on the use of SelectQuery.setRefreshingObjects(..) to determine whether to expire cached result lists. This is no longer the case (setting this flag only refreshes individual objects as it should, and has no effect whatsoever on list caching). Instead caching and cache refreshing is controlled by the cache policy as described above.
    - - -

    Queries Mapped in CayenneModeler

    - -

    The easiest way to set up caching is by creating a named query in CayenneModeler with the appropriate caching type.

    - -

    - -

    Then it can be executed via DataContext:

    +

    Or if we want to refresh the cache, but still keep caching the result after that:

    -
    List objects1 = context.performQuery("MyQuery", false);
    +
    query1.setCachePolicy(QueryCacheStrategy.LOCAL_CACHE_REFRESH);
    +List objects2 = context.performQuery(query1);
     
    -

    The second "false" parameter above indicated that if possible, cached result should be used. Now if we want to force refresh, it can be changed to true (for just this invocation - this does not affect the underlying saved query)

    +

    The example above shows caching with SelectQuery, but it works exactly the same way for SQLTemplate and ProcedureQuery. Similarly SHARED_CACHE and SHARED_CACHE_REFRESH cache policies create cache shared by all ObjectContexts that work on top of a given DataDomain.

    -
    -
    List objects2 = context.performQuery("MyQuery", true);
    -
    -
    +

    There's another optional query property called "cacheGroups" that allows to fine-tune cache expiration in a declarative fashion. When creating a query, a user would specify the names of the cache groups (which are really cache expiration groups) associated with this query, and then separately define expiration policies for the cache groups present in the application. See Query Result Caching for more details.

    -

    Note that parameterized named queries will still work correctly with the cache. We've already mentioned that the users must ensure that two queries must have different names if they fetch logically different data. This is NOT the case with queries stored in the DataMap. If you run the same named query with different sets of parameters, Cayenne will internally generate unique cache keys for each distinct parameter set.

    +

    Queries Mapped in CayenneModeler

    -
    -
    Map parameters = Collections.singletonMap("key", "value1");
    -List objects1 = context.performQuery("MyQuery", parameters, false);
    -
    -
    +

    Named queries created in CayenneModeler can also be configured to use caching, with the same cache strategy and cache groups parameters:

    -

    Now if we run the same query with a different set of parameters, Cayenne will do the right thing and create a separate entry in the cache:

    -
    -
    Map parameters = Collections.singletonMap("key", "value2");
    -List objects2 = context.performQuery("MyQuery", parameters, false);
    -
    -
    +

    -
    +

    NamedQueries that are using caching can be executed just like any other NamedQuery.

    .
    Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Stored Procedures/Executing a Stored Procedure/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Stored%20Procedures/Executing%20a%20Stored%20Procedure/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Stored Procedures/Executing a Stored Procedure/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Stored Procedures/Executing a Stored Procedure/index.html Sun Feb 20 17:21:02 2011 @@ -54,36 +54,34 @@
  • Customization
  • -
    -

    Using QueryResponse to Process Complex Results

    +

    Using QueryResponse to Process Complex Results

    Previous chapter showed how to select a single set of data rows using a ProcedureQuery. In a more general case stored procedures can return multiple sets of data, either as ResultSets or via OUT parameters, execute update/delete/insert queries, etc. To collect the results of execution of such stored procedure, you need to run a query using context's "performGenericQuery" method and inspect returned QueryResponse.

    -
    DataContext ctxt;
    +
    DataContext context;
     
     // "my_procedure" is a name of a stored procedure,
     // that must exist in the DataMap
     ProcedureQuery query = new ProcedureQuery("my_procedure");
     
     // Set "IN" parameter values
    -query.addParam("parameter1", "abc");
    -query.addParam("parameter2", new Integer(3000));
    +query.addParameter("parameter1", "abc");
    +query.addParameter("parameter2", new Integer(3000));
     
     // run query
    -QueryResponse result = ctxt.performGenericQuery(query);
    +QueryResponse result = context.performGenericQuery(query);
     
     // check the results
    -Iterator it = rowSets.iterator();
    -while(result.next()) {
    -     if (result.isList()) {
    -          List list = result.currentList();
    -          // ...
    +for (result.reset(); result.next();) {
    +     if (response.isList()) {
    +         List list = result.currentList();
    +         // ...
          }
    -     else {
    -          int[] updateCounts = result.currentUpdateCount();
    -          // ...
    +    else {
    +         int[] updateCounts = result.currentUpdateCount();
    +         // ...
          }
     }
     
    @@ -94,18 +92,18 @@ query.addParam(

    Stored Procedure can return data back to the application as ResultSets or via OUT parameters. To simplify the processing of the query output, QueryResponse treats OUT parameters as if it was a separate ResultSet. If a stored procedure declares any OUT or INOUT parameters, QueryResponse will contain their returned values in the very first result list:

    -
    DataContext ctxt;
    +
    DataContext context;
     
     // "my_procedure" is a name of a stored procedure,
     // that must exist in the DataMap
     ProcedureQuery query = new ProcedureQuery("my_procedure");
     
     // Set "IN" parameter values
    -query.addParam("paramter1", "abc");
    -query.addParam("parameter2", new Integer(3000));
    +query.addParameter("paramter1", "abc");
    +query.addParameter("parameter2", new Integer(3000));
     
     // run query
    -QueryResponse result = ctxt.performGenericQuery(query);
    +QueryResponse result = context.performGenericQuery(query);
     
     // read OUT parameters
     List outList = result.firstList();
    
    Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Delete/index.html
    URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Tutorial/Tutorial%20Delete/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff
    ==============================================================================
    --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Delete/index.html (original)
    +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Delete/index.html Sun Feb 20 17:21:02 2011
    @@ -68,7 +68,7 @@
     
     

    In the Modeler go to "Artist" ObjEntity, "Relationships" tab and select "Cascade" for the "paintings" relationship delete rule:

    -

    +

    Repeat this step for other relationships:

    Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Java Classes/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Tutorial/Tutorial%20Java%20Classes/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Java Classes/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Java Classes/index.html Sun Feb 20 17:21:02 2011 @@ -98,7 +98,7 @@

    Now let's check the entity class pairs. Each one is made of a superclass (e.g. Artist) and a subclass (e.g. Artist). You should not modify the superclasses whose names start with "" (underscore), as they will be replaced on subsequent generator runs. Instead all custom logic should be placed in the subclasses in "org.example.cayenne.persistent" package - those will never be overwritten by the class generator.

    -

    +

    Class Generation Hint
    Often you'd start by generating classes from the Modeler, but at the later stages of the project the generation is usually automated either via Ant cgen task or Maven cgen mojo. All three methods are interchangeable, however Ant and Maven methods would ensure that you never forget to regenerate classes on mapping changes, as they are integrated into the build cycle.
    Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Object Relational Mapping/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Tutorial/Tutorial%20Object%20Relational%20Mapping/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Object Relational Mapping/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Object Relational Mapping/index.html Sun Feb 20 17:21:02 2011 @@ -62,7 +62,7 @@

    The goal of this section is to learn how to create a simple Object-Relational model with CayenneModeler. We will create a complete ORM model for the following database schema:

    -

    +

    Very often you'd have an existing database already, and it can be quickly imported in Cayenne via "Tools > Reengineer Database Schema". This will save you lots of time compared to manual mapping. However understanding how to create the mapping by hand is important, so we are showing the "manual" approach below.
    @@ -72,7 +72,7 @@

    Select "UntitledDomainMap" on the left-hand side project tree and click "Create DbEntity" button (or use "Project > Create DbEntity" menu). A new DbEntity is created. In "DbEntity Name" field enter "ARTIST". Then click on "Create Attribute" button on the entity toolbar (third button from the left). This action changes the view to the "Attribute" tab and adds a new attribute (attribute means a "table column" in this case) called "untitledAttr". Let's rename it to ID, make it an INTEGER and make it a PK:

    -

    +

    Similarly add NAME VARCHAR(200) and DATE_OF_BIRTH DATE attributes. After that repeat this procedure for PAINTING and GALLERY entities to match DB schema shown above.

    @@ -93,7 +93,7 @@ -

    +

    • Click "Done" to confirm the changes and close the dialog.
    • Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Setup/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Tutorial/Tutorial%20Setup/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Setup/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Setup/index.html Sun Feb 20 17:21:02 2011 @@ -72,7 +72,7 @@

      After downloading Eclipse, unpack it somewhere in the filesystem, and start it. The only plugin that you need for the tutorial is m2eclipse. To install it, in Eclipse go to "Help > Install New Software", then click on "Add.." to add a new download site, and enter "Maven" in the "Name" field, and "http://m2eclipse.sonatype.org/sites/m2e" in the "Location" field. You may install any of the optional components that you think you need, but for this tutorial we only select a few basic components as shown on the following screenshot:

      -

      +

      From here follow the Eclipse dialog instructions to finish the installation.

      Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Starting Project/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Tutorial/Tutorial%20Starting%20Project/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Starting Project/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Starting Project/index.html Sun Feb 20 17:21:02 2011 @@ -62,10 +62,10 @@

    The goal of this section is to create a new Java project in Eclipse containing a basic Cayenne mapping. It presents an introduction to CayenneModeler GUI tool, showing how to create the initial mapping objects: DataDomain, DataNode, DataMap.

    -

    Create a new Project in Eclipse

    +

    Create a new Project in Eclipse

    In Eclipse select "File > New > Other..." and then "Maven > Maven Project". Click "Next". On the following screen check "Create a simple project" checkbox and click "Next" again. In the dialog shown on the screenshot below, fill the "Group Id" and "Artifact Id" fields and click "Finish".
    -

    +

    Now you should have a new empty project in the Eclipse workspace. Check that the project Java compiler settings are correct. Rightclick on the "tutorial" project, select "Properties > Java Compiler" and ensure that "Compiler compliance level" is at least "1.5" (some versions of Maven plugin seem to be setting it to 1.4 by default).

    @@ -77,7 +77,7 @@

    Download the latest release from here. Unpack the distribution somewhere in the file system and start CayenneModeler, following platform-specific instructions. On most platforms it is done simply by doubleclicking the Modeler icon. The welcome screen of the Modeler looks like this:

    -

    +

    Create a New Mapping Project in CayenneModeler

    @@ -99,7 +99,7 @@

    Also you will need to change "Schema Update Strategy". Select "org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy" from the dropdown, so that Cayenne creates a new schema on Derby based on the ORM mapping when the application starts.

    -

    +

    Create a DataMap

    @@ -108,13 +108,13 @@

    You can leave all the DataMap defaults unchanged except for one - "Java Package". Enter "org.example.cayenne.persistent". This name will later be used for all persistent classes.

    -

    +

    Save the Project

    Before you proceed with the actual mapping, let's save the project. Click on "Save" button in the toolbar and navigate to the "tutorial" Eclipse project folder that was created earlier in this section and its "src/main/resources" subfolder and save the project there. Now go back to Eclipse, right click on "tutorial" project and select "Refresh", you will see three Cayenne XML files.

    -

    +

    Note that the location of the XML files is not coincidental. Cayenne runtime looks for "cayenne.xml" file in the application CLASSPATH and "src/main/resources" folder should already be a "class folder" in Eclipse for our project (and is also a standard location that Maven would copy to a jar file, if we were using Maven from command-line).

    Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Webapp/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne%20Guide/Tutorial/Tutorial%20Webapp/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Webapp/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Cayenne Guide/Tutorial/Tutorial Webapp/index.html Sun Feb 20 17:21:02 2011 @@ -248,7 +248,7 @@ -

    +

    • Click "Apply" and "Run". On the first execution it may take a few minutes for Jetty plugin to download all dependencies, but eventually you'll see the logs like this:
    • @@ -331,7 +331,7 @@ INFO: +++ transaction committed.
    -

    +

    You are done with the tutorial!

    Modified: cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Overview/Guide to 3.1 Features/index.html URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Overview/Guide%20to%203.1%20Features/index.html?rev=1072639&r1=1072638&r2=1072639&view=diff ============================================================================== --- cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Overview/Guide to 3.1 Features/index.html (original) +++ cayenne/main/trunk/docs/doc/src/main/resources/doc/Documentation/Overview/Guide to 3.1 Features/index.html Sun Feb 20 17:21:02 2011 @@ -47,6 +47,7 @@
  • Cayenne Configuration
  • Framework API
  • CayenneModeler
  • +
  • Lifecycle Extensions
  • @@ -67,7 +68,7 @@

    Dependency Injection Container

    -

    Cayenne 3.1 runtime stack is built around the ideas of Dependency Injection (DI), making it extremely flexible and easy to extend. It bundles a small, flexible annotations-based DI to configure its services. The idea behind Cayenne DI is to provide DI services and extension points to Cayenne, but do not interfere with other DI containers that may be present in the application. I.e. it is invisible to the users who do not care about advanced Cayenne customization.

    +

    Cayenne 3.1 runtime stack is built around the ideas of Dependency Injection (DI), making it extremely flexible and easy to extend. It bundles a small, flexible annotations-based DI container to configure its services. The container provides DI services and exposes Cayenne extension points, but does not interfere with other DI containers that may be present in the application. I.e. it is invisible to the users who do not care about advanced Cayenne customization.

    Bootstrapping Cayenne in Various Environments

    @@ -92,14 +93,72 @@

    Framework API

    -

    TODO... See UPGRADE.txt for the list of changes

    +

    See UPGRADE.txt for the full list of changes

    + +

    Lifecycle Listener Annotations

    + +

    Cayenne 3.1 features support for annotations on lifecycle listeners (but not yet on entity callback methods) that simplifies registering listeners via API. Our experience with Cayenne 3.0 shows that mapping listeners in the Modeler doesn't scale well to complex applications, and 3.0 API for mapping the listeners is hard to use. In 3.1 you can annotate listener methods and register multiple callback methods with a single call.

    + +
    +
    // declare a listener with annotated methods
    +class MyListener {
    +    @PostLoad(Entity1.class)
    +    @PostPersist(Entity1.class)
    +    void postLoad(Object object) {
    +        ....
    +    }
    +}
    +
    +// register a listener
    +ServerRuntime runtime = ..
    +MyListener listener = new MyListener();
    +runtime.getChannel().getEntityResolver().getCallbackRegistry().addListener(listener);
    +
    + +

    Moreover, unlike JPA annotations, Cayenne allows to attach a listener to a set of entities not known to the listener upfront, but that are all annotated with some custom annotation:

    + +
    +
    class MyListener {
    +    @PostLoad(entityAnnotations = CustomAnnotation.class)
    +    void postLoad(Object object) {
    +        ....
    +    }
    +}
    +
    + + +

    DataChannelFilter for Intercepting DataDomain Operations

    + +

    Cayenne now features a DataChannelFilter interface that allows to intercept and alter all DataChannel traffic (i.e. selects and commits between a DataContext and DataDomain). It provides a chain of command API very similar to servlet filters. Filters are widely used by "cayenne-lifecyle" extensions and allow to build powerful custom object lifecycle-aware code. To install a filter, the following API is used:

    + +
    +
    class MyFilter implement DataChannelFilter { .. }
    +
    +MyFilter filter = new MyFilter();
    +ServerRuntime runtime = ..
    +runtime.getDataDomain().addFilter(filter);
    +
    + +

    Very often filters mark some of their own methods with lifecycle annotations so that certain operations can be triggered by Cayenne inside the scope of filter's onQuery() or onSync() methods. To ensure annotated methods are invoked, filter registration should be combined with listener registration:

    + +
    +
    MyFilter filter = new MyFilter();
    +ServerRuntime runtime = ..
    +runtime.getDataDomain().addFilter(filter);
    +runtime.getDataDomain().getEntityResolver().getCallbackRegistry().addListener(filter);
    +// noticed that by default runtime.getDataDomain() is equivalent to runtime.getChannel()
    +
    +

    CayenneModeler

    Java Preferences API

    We got rid of HSQLDB-based preferences storage, and are using standard Java Preferences API for the Modeler preferences. This solved a long-standing stability issue with Modeler preferences. So no more lost user preferences.

    -
    + +

    Lifecycle Extensions

    + +

    Cayenne 3.1 includes an optional cayenne-lifecyle module that implements a few useful extensions based on DataChannelFilters and lifecycle annotations. Those include a concept of UUID (which is a String URL-friendly representation of ObjectId), support for (de)referencing objects by UUID, UUID-based relationships, annotation-based cache groups invalidation, annotation-based audit of object changes, etc.

    .