blob: 26d1c199e09e0991175b62858bc5f9198e833cce [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.3">
<link rel="apple-touch-icon" sizes="180x180" href="/img/favicon/apple-touch-icon-04cb17e028.png">
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon/favicon-32x32-12431ee8eb.png">
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon/favicon-16x16-4f316e4d55.png">
<link rel="manifest" href="/img/favicon/manifest-65e6aaa49e.json">
<link rel="mask-icon" href="/img/favicon/safari-pinned-tab-558c1991b1.svg" color="#dc5656">
<link rel="shortcut icon" href="/img/favicon/favicon-6cef91375b.ico">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/img/favicon/mstile-144x144-34e7696278.png">
<meta name="msapplication-config" content="/img/favicon/browserconfig-82ff158058.xml">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="https://cayenne.apache.org/css/styles-9ee2e6e330.css"/>
<script src="https://cayenne.apache.org/js/bundle-c0e6356367.js"></script>
<title>Cayenne Guide 5.0 · Expressions &middot; Apache Cayenne</title>
</head>
<body class="cd-head">
<header class="page-header">
<nav id="topbar" class="bg-dark" aria-label="breadcrumb" role="navigation">
<ul class="breadcrumb breadcrumb-sm breadcrumb-dark container mb-0">
<li class="breadcrumb-item dropdown">
<a class="dropdown-toggle text-nowrap pr-1" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img class="mw-15px mr-1" src="/img/feather-641aa69d09.svg" />Apache Software Foundation</a>
<div class="dropdown-menu rounded-0" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="https://www.apache.org">Apache Homepage</a>
<a class="dropdown-item" href="https://www.apache.org/licenses/">License</a>
<a class="dropdown-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
<a class="dropdown-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a>
<a class="dropdown-item" href="https://www.apache.org/security/">Security</a>
<a class="dropdown-item" href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy</a>
<a class="ml-1 mt-1 acevent" data-format="wide" data-mode="dark" data-width="120"></a>
</div>
</li>
</ul>
</nav>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="https://cayenne.apache.org/">
<img src="/img/logo_mono_full-d7a19eef61.svg" alt="Apache Cayenne" />
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="mainMenu">
<ul class="navbar-nav mt-3 mt-lg-0 mr-auto">
<li class="nav-item">
<a class="nav-link" href="/download/">DOWNLOAD</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/docs/4.2/getting-started-guide/">DOCUMENTATION</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/about/support/">SUPPORT</a>
</li>
</ul>
<ul class="navbar-nav flex-row justify-content-center mt-2 mt-lg-0 mb-2 mb-lg-0 " id="social-links-menu">
<li class="nav-item d-flex">
<a class="nav-link d-flex justify-content-center align-items-center" href="https://github.com/apache/cayenne">
<img src="/img/icon_octocat_stars-c24dac94b8.svg" alt="GitHub" />
</a>
</li>
<li class="nav-item d-flex">
<a class="nav-link d-flex justify-content-center align-items-center" href="https://twitter.com/ApacheCayenne">
<img src="/img/icon_twitter-220a129d14.svg" alt="Twitter" />
</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<main>
<div class="cd-top-sidebar bb">
<div class="container">
<div class="row no-gutters">
<div class="col-12 col-lg-4 col-xl-3 br cd-sidebar1">
<ul class="nav" role="tablist">
<li class="nav-item dropdown mw-100">
<a class="nav-link dropdown-toggle text-truncate" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
Cayenne Version 5.0
</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="/docs/5.0/cayenne-guide/">Version 5.0 (Alpha)</a><a class="dropdown-item" href="/docs/4.2/getting-started-guide/">Version 4.2 (Stable)</a><a class="dropdown-item" href="/docs/4.1/getting-started-guide/">Version 4.1 (Stable)</a><a class="dropdown-item" href="/docs/4.0/getting-started-guide/">Version 4.0 (Aging)</a><a class="dropdown-item" href="/docs/3.1/getting-started-guide/">Version 3.1 (Legacy)</a>
</div>
</li>
</ul>
</div>
<div class="col-12 col-lg-8 col-xl-9"> </div>
</div>
</div>
</div>
<div class="container">
<div class="row no-gutters ">
<div class="col-12 col-lg-4 col-xl-3 br py-2 bg-gray-100 cd-sidebar">
<div class="tab-content" id="cd-docs-nav">
<div class="cd-toc-item">
<span class="cd-toc-link active">Cayenne Guide 5.0</span><div id="toc" class="toc toc-side">
<div id="toctitle">
Table of Contents
</div>
<ul class="sectlevel1 nav">
<li><a href="/docs/5.0/cayenne-guide/object-relational-mapping-with-cayenne" class="nav-link" id="object-relational-mapping-with-cayenne">1. Object Relational Mapping with Cayenne</a>
<ul class="sectlevel2 nav">
<li><a href="/docs/5.0/cayenne-guide/setup" class="nav-link" id="setup">1.1. Setup</a></li>
<li><a href="/docs/5.0/cayenne-guide/cayenne-mapping-structure" class="nav-link" id="cayenne-mapping-structure">1.2. Cayenne Mapping Structure</a></li>
<li><a href="/docs/5.0/cayenne-guide/cayenne-modeler" class="nav-link" id="cayenne-modeler">1.3. CayenneModeler Application</a></li>
</ul></li>
<li><a href="/docs/5.0/cayenne-guide/cayenne-framework" class="nav-link" id="cayenne-framework">2. Cayenne Framework</a>
<ul class="sectlevel2 nav">
<li><a href="/docs/5.0/cayenne-guide/including-cayenne-in-project" class="nav-link" id="including-cayenne-in-project">2.1. Including Cayenne in a Project</a></li>
<li><a href="/docs/5.0/cayenne-guide/starting-cayenne" class="nav-link" id="starting-cayenne">2.2. Starting Cayenne</a></li>
<li><a href="/docs/5.0/cayenne-guide/persistent-objects-objectcontext" class="nav-link" id="persistent-objects-objectcontext">2.3. Persistent Objects and ObjectContext</a></li>
<li><a href="/docs/5.0/cayenne-guide/expressions" class="nav-link" id="expressions">2.4. Expressions</a></li>
<li><a href="/docs/5.0/cayenne-guide/orderings" class="nav-link" id="orderings">2.5. Orderings</a></li>
<li><a href="/docs/5.0/cayenne-guide/queries" class="nav-link" id="queries">2.6. Queries</a></li>
<li><a href="/docs/5.0/cayenne-guide/lifecycle-events" class="nav-link" id="lifecycle-events">2.7. Lifecycle Events</a></li>
<li><a href="/docs/5.0/cayenne-guide/performance-tuning" class="nav-link" id="performance-tuning">2.8. Performance Tuning</a></li>
<li><a href="/docs/5.0/cayenne-guide/customizing-cayenne-runtime" class="nav-link" id="customizing-cayenne-runtime">2.9. Customizing Cayenne Runtime</a></li>
</ul></li>
<li><a href="/docs/5.0/cayenne-guide/db-first-flow" class="nav-link" id="db-first-flow">3. DB-First Flow</a>
<ul class="sectlevel2 nav">
<li><a href="/docs/5.0/cayenne-guide/re-introduction" class="nav-link" id="re-introduction">3.1. Introduction</a></li>
<li><a href="/docs/5.0/cayenne-guide/re-filtering" class="nav-link" id="re-filtering">3.2. Filtering</a></li>
<li><a href="/docs/5.0/cayenne-guide/re-relationships-loading-control" class="nav-link" id="re-relationships-loading-control">3.3. Other Settings</a></li>
<li><a href="/docs/5.0/cayenne-guide/re-modeler" class="nav-link" id="re-modeler">3.4. Reverse Engineering in Cayenne Modeler</a></li>
</ul></li>
<li><a href="/docs/5.0/cayenne-guide/additional-modules" class="nav-link" id="additional-modules">4. Additional Modules</a>
<ul class="sectlevel2 nav">
<li><a href="/docs/5.0/cayenne-guide/ext-cache-invalidation" class="nav-link" id="ext-cache-invalidation">4.1. Cache Invalidation Extension</a></li>
<li><a href="/docs/5.0/cayenne-guide/ext-commit-log" class="nav-link" id="ext-commit-log">4.2. Commit log extension</a></li>
<li><a href="/docs/5.0/cayenne-guide/ext-crypto" class="nav-link" id="ext-crypto">4.3. Crypto extension</a></li>
<li><a href="/docs/5.0/cayenne-guide/ext-jcache" class="nav-link" id="ext-jcache">4.4. JCache integration</a></li>
<li><a href="/docs/5.0/cayenne-guide/ext-project-compatibility" class="nav-link" id="ext-project-compatibility">4.5. Project compatibility extension</a></li>
<li><a href="/docs/5.0/cayenne-guide/ext-velocity" class="nav-link" id="ext-velocity">4.6. Apache Velocity Extension</a></li>
<li><a href="/docs/5.0/cayenne-guide/ext-osgi" class="nav-link" id="ext-osgi">4.7. Cayenne OSGI extension</a></li>
</ul></li>
<li><a href="/docs/5.0/cayenne-guide/build_tools" class="nav-link" id="build_tools">5. Build Tools</a>
<ul class="sectlevel2 nav">
<li><a href="/docs/5.0/cayenne-guide/maven_plugin" class="nav-link" id="maven_plugin">5.1. Maven Plugin</a></li>
<li><a href="/docs/5.0/cayenne-guide/gradle_plugin" class="nav-link" id="gradle_plugin">5.2. Gradle Plugin</a></li>
<li><a href="/docs/5.0/cayenne-guide/ant_tasks" class="nav-link" id="ant_tasks">5.3. Ant Tasks</a></li>
</ul></li>
<li><a href="/docs/5.0/cayenne-guide/appendix-a-configuration-properties" class="nav-link" id="appendix-a-configuration-properties">6. Appendix A. Configuration Properties</a></li>
<li><a href="/docs/5.0/cayenne-guide/appendix-b-service-collections" class="nav-link" id="appendix-b-service-collections">7. Appendix B. Service Collections</a></li>
</ul>
</div>
</div>
<div class="cd-toc-item">
</div>
</div>
</div>
<div class="col-12 col-lg-8 col-xl-9 py-3 pl-lg-5 cd-content">
<article>
<header>
</header>
<section>
<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 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 situations. The general structure of path expressions is the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java"> [db:]segment[+][.segment[+]...]</code></pre>
</div>
</div>
<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. The path must have at least one segment; segments are separated by dot (".").</p></li>
<li>
<p>`` 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>
<div class="paragraph">
<p>An object path expression represents a chain of property names rooted in a certain (unspecified during expression creation) object and "navigating" to its related value. E.g. a path expression "artist.name" might be a property path starting from a Painting object, pointing to the related Artist object, and then to its name attribute. A few more examples:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>name</code> - can be used to navigate (read) the "name" property of a Person (or any other type of object that has a "name" property).</p></li>
<li>
<p><code>artist.exhibits.closingDate</code> - can be used to navigate to a closing date of any of the exhibits of a Painting’s Artist object.</p></li>
<li>
<p><code>artist.exhibits+.closingDate</code> - same as the previous example, but when translated into SQL, an OUTER JOIN will be used for "exhibits".</p></li>
</ul>
</div>
<div class="paragraph">
<p>Similarly a database path expression is a dot-separated path through DB table joins and columns. In Cayenne joins are mapped as DbRelationships with some symbolic names (the closest concept to DbRelationship name in the DB world is a named foreign key constraint. But DbRelationship names are usually chosen arbitrarily, without regard to constraints naming or even constraints presence). A database path therefore might look like this - <code>db:dbrelationshipX.dbrelationshipY.COLUMN_Z"</code>. More specific examples:</p>
</div>
<div class="ulist">
<ul>
<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 the explicit path or an alias:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>artist.exhibits.closingDate</code> - full path</p></li>
<li>
<p><code>e.closingDate</code> - alias "e" is used for <code>artist.exhibits</code>.</p></li>
</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 <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 matching paths.</p>
</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 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">
<pre class="highlight"><code class="language-java java" data-lang="java">String expString = "name like 'A%' and price &lt; 1000";
Expression exp = ExpressionFactory.exp(expString);</code></pre>
</div>
</div>
<div class="paragraph">
<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 match Paintings", we are implying that there may be other entities for which this expression is valid. Now the expression details…​</p>
</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>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">name = 'ABC'
// double quotes are escaped inside Java Strings of course
name = \"ABC\"</code></pre>
</div>
</div>
<div class="paragraph">
<p>Case sensitivity. Expression operators are case sensitive and are usually lowercase. Complex words follow the Java camel-case style:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">// valid
name likeIgnoreCase 'A%'
// invalid - will throw a parse exception
name LIKEIGNORECASE 'A%'</code></pre>
</div>
</div>
<div class="paragraph">
<p>Grouping with parenthesis:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">value = (price + 250.00) * 3</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). 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">
<pre class="highlight"><code class="language-java java" data-lang="java">// object path
name = 'Salvador Dali'
// same object path - a rarely used form
obj:name = 'Salvador Dali'
// multi-segment object path
artist.name = 'Salvador Dali'
// db path
db:NAME = 'Salvador Dali'
// enumeration constant
name = enum:org.foo.EnumClass.VALUE1</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>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">name like 'A%'</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 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 <code>Date</code>, a <code>Persistent</code>, an <code>ObjectId</code>), parameterizing the expression is the only way to represent it as String. Here are examples of both positional and named parameter bindings:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">Expression template = ExpressionFactory.exp("name = $name");
...
// name binding
Map p1 = Collections.singletonMap("name", "Salvador Dali");
Expression qualifier1 = template.params(p1);
...
// positional binding
Expression qualifier2 = template.paramsArray("Monet");</code></pre>
</div>
</div>
<div class="paragraph">
<p>Positional binding is usually shorter. You can pass positional bindings to the <code>exp(..)</code> factory method (its second argument is a params vararg):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">Expression qualifier = ExpressionFactory.exp("name = $name", "Monet");</code></pre>
</div>
</div>
<div class="paragraph">
<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">
<pre class="highlight"><code class="language-java java" data-lang="java">Expression qualifier = ExpressionFactory.exp("name like $name", "Salvador%");</code></pre>
</div>
</div>
<div class="paragraph">
<p>When matching on a relationship, the value parameter must be either a Persistent object, an <code>org.apache.cayenne.ObjectId</code>, or a numeric ID value (for single column IDs). E.g.:</p>
</div>
<div class="listingblock">
<div class="content">
<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 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">
<pre class="highlight"><code class="language-java java" data-lang="java">Expression template = ExpressionFactory.exp("name like $name and dateOfBirth &gt; $date");
...
Map p1 = Collections.singletonMap("name", "Salvador%");
Expression qualifier1 = template.params(p1);
// "qualifier1" is now "name like 'Salvador%'".
// 'dateOfBirth &gt; $date' condition was pruned, as no value was specified for
// the $date parameter</code></pre>
</div>
</div>
<div class="paragraph">
<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 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">
<pre class="highlight"><code class="language-java java" data-lang="java">// String expression: name like 'A%' and price &lt; 1000
Expression e1 = ExpressionFactory.likeExp("name", "A%");
Expression e2 = ExpressionFactory.lessExp("price", 1000);
Expression finalExp = e1.andExp(e2);</code></pre>
</div>
</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">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, 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">
<pre class="highlight"><code class="language-java java" data-lang="java">Expression matchAllExp(String path, Collection values)
Expression matchAllExp(String path, Object... values)</code></pre>
</div>
</div>
<div class="paragraph">
<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 expressions, forcing separate joins.</p>
</div>
<div class="paragraph">
<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&lt;String&gt;
Expression e1 = Artist.NAME.eq("Pablo");
// Chaining multiple properties into a path.
// Painting.ARTIST is generated by Cayenne and has a type of Property&lt;Artist&gt;
Expression e2 = Painting.ARTIST.dot(Artist.NAME).eq("Pablo");</code></pre>
</div>
</div>
<div class="paragraph">
<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 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>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">Expression e = Artist.NAME.in("John", "Bob");
Artist artist = ...
if(e.match(artist)) {
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Reading property value:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">String name = Artist.NAME.path().evaluate(artist);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Filtering a list of objects:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">Expression e = Artist.NAME.in("John", "Bob");
List&lt;Artist&gt; unfiltered = ...
List&lt;Artist&gt; filtered = e.filterObjects(unfiltered);</code></pre>
</div>
</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">Current limitation of in-memory expressions is that no collections are permitted in the property path.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect3">
<h4 id="translating-expressions-to-ejbql"><a class="anchor" href="#translating-expressions-to-ejbql"></a>2.4.5. Translating Expressions to EJBQL</h4>
<div class="paragraph">
<p><a href="/docs/5.0/cayenne-guide/queries#ejbql">EJBQL</a> is a textual query language that can be used with Cayenne. In some situations, it is convenient to be able to convert Expression instances into EJBQL. Expressions support this conversion. An example is shown below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">String serial = ...
Expression e = Pkg.SERIAL.eq(serial);
List&lt;Object&gt; params = new ArrayList&lt;Object&gt;();
EJBQLQuery query = new EJBQLQuery("SELECT p FROM Pkg p WHERE " + e.toEJBQL(params,"p");
for(int i=0;i&lt;params.size();i++) {
query.setParameter(i+1, params.get(i));
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This would be equivalent to the following purely EJBQL querying logic;</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">EJBQLQuery query = new EJBQLQuery("SELECT p FROM Pkg p WHERE p.serial = ?1");
query.setParameter(1,serial);</code></pre>
</div>
</div>
</div>
</div>
</section>
<footer>
<div class="row">
<div class="col-6 col-md-3 text-center text-md-left">
&nbsp;
</div>
<div class="col-18 col-md-9 text-center text-md-right">
<a class="btn btn-link" href='/docs/5.0/cayenne-guide/orderings/'>
<span class="d-block d-md-none text-muted">Next: </span>
Next: Cayenne Guide 5.0 · Orderings
<i class="small fa fa-chevron-right ml-3l2 d-none d-md-inline"></i>
</a>
</div>
</div>
</footer>
</article>
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=5c836e39-be6b-4a21-a946-a97b5b69f172" />
</div>
</div>
</div>
</main>
<footer class="bg-dark">
<div class="footer-nav container text-center text-lg-left pb-3">
<div class="row pt-5 pb-3">
<div class="col-sm-6 col-lg-3">
<h4>About</h4>
<ul class="list-unstyled">
<li>
<a href="/why-cayenne.html">Why Cayenne?</a>
</li>
<li>
<a href="/download/">Download</a>
</li>
<li>
<a href="/success-stories.html">Success Stories</a>
</li>
<li>
<a href="/about/support/">Support</a>
</li>
</ul>
</div>
<div class="col-sm-6 col-lg-3">
<h4>Documentation</h4>
<ul class="list-unstyled">
<li>
<a href="/docs/4.0/getting-started-guide/">Getting Started (4.0)</a>
</li>
<li>
<a href="/docs/4.1/getting-started-guide/">Getting Started (4.1)</a>
</li>
<li>
<a href="/docs/4.2/getting-started-guide/">Getting Started (4.2)</a>
</li>
<li>
<a href="/docs/4.0/cayenne-guide/">Cayenne Guide (4.0)</a>
</li>
<li>
<a href="/docs/4.1/cayenne-guide/">Cayenne Guide (4.1)</a>
</li>
<li>
<a href="/docs/4.2/cayenne-guide/">Cayenne Guide (4.2)</a>
</li>
<li>
<a href="/docs/4.1/getting-started-db-first/">Database First tutorial (4.1)</a>
</li>
<li>
<a href="/docs/4.2/getting-started-db-first/">Database First tutorial (4.2)</a>
</li>
<li>
<a href="/legacy/legacy-docs/">Legacy Documentation</a>
</li>
</ul>
</div>
<div class="col-sm-6 col-lg-3">
<h4>Collaboration</h4>
<ul class="list-unstyled">
<li>
<a href="https://issues.apache.org/jira/browse/CAY">Bug/Feature Tracker</a>
</li>
<li>
<a href="/mailing-lists.html">Mailing Lists</a>
</li>
<li>
<a href="/dev/code-repository.html">Code Repository</a>
</li>
<li>
<a href="/dev/">Developer Guide</a>
</li>
<li>
<a href="/how-can-i-help.html">How can I help?</a>
</li>
<li>
<a href="/contributors.html">Contributors</a>
</li>
<li>
<a href="/thanks.html">Thanks</a>
</li>
</ul>
</div>
<div class="col-sm-6 col-lg-3">
<h4>News</h4>
<ul class="list-multiline-items list-unstyled mb-0">
<li>
<time datetime="2023-05-25 18:00:00 &#43;0300 &#43;0300" class="xsmall d-block">May 25, 2023</time>
<a href="/2023/05/cayenne-42-final-released/">Cayenne 4.2 Final Released</a>
</li>
<li>
<time datetime="2023-03-02 12:00:00 &#43;0300 &#43;0300" class="xsmall d-block">Mar 02, 2023</time>
<a href="/2023/03/cayenne-403-released/">Cayenne 4.0.3 Released</a>
</li>
<li>
<time datetime="2022-12-05 12:00:00 &#43;0300 &#43;0300" class="xsmall d-block">Dec 05, 2022</time>
<a href="/2022/12/cayenne-42rc2-released/">Cayenne 4.2 Release Candidate 2 Released</a>
</li>
</ul>
<a class="btn-link text-uppercase xsmall" href="https://cayenne.apache.org/news">
More news
<i class="fa fa-lg fa-long-arrow-right" aria-hidden="true"></i>
</a>
</div>
</div>
<hr class="mt-0 mb-3" />
<p class="copy xsmall text-center mw-75 mx-auto mb-0">
Copyright © 2001-2024 Apache Software Foundation. Apache Cayenne, Cayenne, Apache, the Apache feather logo, and the Apache Cayenne project logo are trademarks of The Apache Software Foundation.
<a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy policy</a>.
<img class="d-block mx-auto mt-2" src="/img/logo_mono-3302daa3cf.svg" alt="Apache Cayenne" />
</p>
</div>
</footer>
</body>
</html>