| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <title xmlns:d="http://docbook.org/ns/docbook">Chapter 7. Expressions</title><link rel="stylesheet" type="text/css" href="css/cayenne-doc.css"><meta xmlns:d="http://docbook.org/ns/docbook" name="keywords" content="Cayenne 4.0 documentation"><meta xmlns:d="http://docbook.org/ns/docbook" name="description" content="User documentation for Apache Cayenne version 4.0"><link rel="home" href="index.html" title="Cayenne Guide"><link rel="up" href="cayenne-guide-part2.html" title="Part II. Cayenne Framework"><link rel="prev" href="persistent-objects-objectcontext.html" title="Chapter 6. Persistent Objects and ObjectContext"><link rel="next" href="orderings.html" title="Chapter 8. Orderings"><script xmlns:d="http://docbook.org/ns/docbook" type="text/javascript"> |
| var _gaq = _gaq || []; |
| _gaq.push(['_setAccount', 'UA-7036673-1']); |
| _gaq.push(['_trackPageview']); |
| (function() { |
| var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
| ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
| var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
| })(); |
| </script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div xmlns:d="http://docbook.org/ns/docbook" class="navheader"><table width="100%" summary="Navigation header"><tr><th class="versioninfo">v.4.0 (4.0.M5)</th><th align="center">Chapter 7. Expressions</th><th></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="persistent-objects-objectcontext.html">Prev</a> </td><th width="60%" align="center"><a accesskey="u" href="cayenne-guide-part2.html">Part II. Cayenne Framework</a></th><td width="20%" align="right"> <a accesskey="n" href="orderings.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="expressions"></a>Chapter 7. Expressions</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="expressions.html#expressions-overview">Expressions Overview</a></span></dt><dt><span class="section"><a href="expressions.html#path-expressions">Path Expressions</a></span></dt><dt><span class="section"><a href="expressions.html#expressions-from-strings">Creating Expressions from Strings </a></span></dt><dt><span class="section"><a href="expressions.html#expressions-with-expressionfactory">Creating Expressions via API</a></span></dt><dt><span class="section"><a href="expressions.html#expressions-in-memory">Evaluating Expressions in Memory</a></span></dt><dt><span class="section"><a href="expressions.html#expressions-to-ejbql">Translating Expressions to EJBQL</a></span></dt></dl></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a name="expressions-overview"></a>Expressions Overview</h2></div></div></div><p>Cayenne provides a simple yet powerful object-based expression language. The most common |
| usese 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></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a name="path-expressions"></a>Path Expressions</h2></div></div></div><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. General structure of |
| path expressions is the following:</p><pre class="programlisting"> [db:]segment[+][.segment[+]...]</pre><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>"db:" is an optional prefix indicating that the following path is a DB |
| path. Otherwise it is an object path.</p></li><li class="listitem"><p>"segment" is a name of a property (relationship or attribute in Cayenne |
| terms) in the path. Path must have at least one segment; segments are |
| separated by dot (".").</p></li><li class="listitem"><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><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><p> |
| </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>"name" - 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 class="listitem"><p>"artist.exhibits.closingDate" - can be used to navigate to a closing date |
| of any of the exhibits of a Painting's Artist object.</p></li><li class="listitem"><p>"artist.exhibits+.closingDate" - same as the previous example, but when |
| translated into SQL, an OUTER JOIN will be used for "exhibits".</p></li></ul></div><p> |
| </p><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 - "db:dbrelationshipX.dbrelationshipY.COLUMN_Z". More specific examples:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>"db:NAME" - can be used to navigate to the value of "NAME" column of some |
| unspecified table.</p></li><li class="listitem"><p>"db:artist.artistExhibits.exhibit.CLOSING_DATE" - can be used to match a |
| closing date of any of the exhibits of a related artist record.</p></li></ul></div><p>Cayenne supports "aliases" in path Expressions. E.g. the same expression can be |
| written using explicit path or an alias:</p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>"artist.exhibits.closingDate" - full path</p></li><li class="listitem"><p>"e.closingDate" - alias "e" is used for "artist.exhibits".</p></li></ul></div><p>SelectQuery using the second form of the path expression must be made |
| aware of the alias via <span class="italic"> |
| "SelectQuery.aliasPathSplits(..)"</span>, 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></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a name="expressions-from-strings"></a>Creating Expressions from Strings </h2></div></div></div><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 class="code">ExpressionFactory.exp</code> static |
| method. Here is an |
| example:</p><pre class="programlisting">String expString = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"name like 'A%' and price < 1000"</span>; |
| Expression exp = ExpressionFactory.exp(expString);</pre><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 used to match Paintings", we are implying that there may be other |
| entities, for which this expression is valid. Now the expression details... </p><p><span class="italic">Character constants</span> that are not paths or numeric values |
| should be enclosed in single or double quotes. Two of the expressions below are |
| equivalent:</p><pre class="programlisting">name = 'ABC' |
| |
| // double quotes are escaped inside Java Strings of course |
| name = \"ABC\"</pre><p><span class="italic">Case sensitivity.</span> Expression operators are case |
| sensitive and are usually lowercase. Complex words follow the Java camel-case |
| style:</p><pre class="programlisting">// valid |
| name likeIgnoreCase 'A%' |
| |
| // invalid - will throw a parse exception |
| name LIKEIGNORECASE 'A%'</pre><p><span class="italic">Grouping with parenthesis:</span> |
| </p><pre class="programlisting">value = (price + 250.00) * 3</pre><p> |
| </p><p><span class="italic">Path prefixes.</span> Object expressions are unquoted strings, |
| optionally prefixed by "obj:" (usually they are not prefixed at all actually). Database |
| expressions are always prefixed with "db:". A special kind of prefix, not discussed yet |
| is "enum:" that prefixes an enumeration |
| constant:</p><pre class="programlisting">// 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</pre><p> |
| <span class="italic">Binary conditions</span> 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><pre class="programlisting">name like 'A%'</pre><p> |
| <span class="italic">Parameters.</span> 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 parameter |
| bindings:</p><pre class="programlisting">Expression template = ExpressionFactory.exp(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"name = $name"</span>); |
| ... |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// name binding</span> |
| Map p1 = Collections.singletonMap(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"name"</span>, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Salvador Dali"</span>); |
| Expression qualifier1 = template.params(p1); |
| ... |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// positional binding</span> |
| Expression qualifier2 = template.paramsArray(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Monet"</span>);</pre><p>Positional binding is usually shorter. You can pass positional bindings to the |
| <code class="code">"exp(..)"</code> factory method (its second argument is a params |
| vararg):</p><pre class="programlisting">Expression qualifier = ExpressionFactory.exp("name = $name", "Monet");</pre><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><pre class="programlisting">Expression qualifier = ExpressionFactory.exp(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"name like $name"</span>, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Salvador%"</span>);</pre><p>When |
| matching on a relationship, the value parameter must be either a Persistent object, an |
| <code class="code">org.apache.cayenne.ObjectId</code>, or a numeric ID value (for single column |
| IDs). |
| E.g.:</p><pre class="programlisting">Artist dali = ... <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// asume we fetched this one already</span> |
| Expression qualifier = ExpressionFactory.exp(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"artist = $artist"</span>, dali);</pre><p>When |
| using positional binding, Cayenne would expect values for <span class="bold"><strong>all</strong></span> 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><pre class="programlisting">Expression template = ExpressionFactory.exp(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"name like $name and dateOfBirth > $date"</span>); |
| ... |
| Map p1 = Collections.singletonMap(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"name"</span>, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Salvador%"</span>); |
| Expression qualifier1 = template.params(p1); |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// "qualifier1" is now "name like 'Salvador%'".</span> |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// 'dateOfBirth > $date' condition was pruned, as no value was specified for </span> |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// the $date parameter</span></pre><p><span class="italic">Null handling.</span> Handling of Java nulls as operands |
| is no different from normal values. Instead of using special conditional operators, like |
| SQL does (IS NULL, IS NOT NULL), "=" and "!=" expressions are used |
| directly with null values. It is up to Cayenne to translate expressions with nulls to |
| the valid SQL.</p><p> |
| </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>A formal definition of the expression grammar is provided in Appendix C</p></div><p> |
| </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a name="expressions-with-expressionfactory"></a>Creating Expressions via API</h2></div></div></div><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 class="code">ExpressionFactory</code> class (that |
| we've seen already), <code class="code">Property</code> class and <code class="code">Expression</code> class |
| itself. <code class="code">ExpressionFactory</code> contains a number of self-explanatory static |
| methods that can be used to build expressions. E.g.:</p><p> |
| </p><pre class="programlisting"><span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// String expression: name like 'A%' and price < 1000</span> |
| Expression e1 = ExpressionFactory.likeExp(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"name"</span>, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"A%"</span>); |
| Expression e2 = ExpressionFactory.lessExp(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"price, 1000); |
| </span>Expression finalExp = e1.andExp(e2); </pre><p> |
| </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The last line in the example above shows how to create a new expression by |
| "chaining" two other epxressions. A common error when chaining |
| expressions is to assume that "andExp" and "orExp" append |
| another expression to the current expression. In fact a new expression is |
| created. I.e. Expression API treats existing expressions as immutable.</p></div><p> |
| </p><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><pre class="programlisting">Expression matchAllExp(String path, Collection values) |
| Expression matchAllExp(String path, Object... values)</pre><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 class="code">"|exhibits.paintings"</code>, <code class="code">"exhibits|paintings"</code>, etc. |
| Internally Cayenne would generate distinct aliases for each of the split expressions, |
| forcing separate joins.</p><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><pre class="programlisting">// 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.. |
| // Painting.ARTIST is generated by Cayenne and has a type of Property<Artist> |
| Expression e2 = Painting.ARTIST.dot(Artist.NAME).eq("Pablo");</pre><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></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a name="expressions-in-memory"></a>Evaluating Expressions in Memory</h2></div></div></div><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>Checking whether an object satisfies an |
| expression:</p><pre class="programlisting">Expression e = Artist.NAME.in(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"John"</span>, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Bob"</span>); |
| Artist artist = ... |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">if</span>(e.match(artist)) { |
| ... |
| }</pre><p>Reading |
| property |
| value:</p><pre class="programlisting">String name = Artist.NAME.path().evaluate(artist);</pre><p>Filtering a list of |
| objects:</p><pre class="programlisting">Expression e = Artist.NAME.in(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"John"</span>, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Bob"</span>); |
| List<Artist> unfiltered = ... |
| List<Artist> filtered = e.filterObjects(unfiltered);</pre><p> |
| </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>Current limitation of in-memory expressions is that no collections are |
| permitted in the property path.</p></div><p> |
| </p></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a name="expressions-to-ejbql"></a>Translating Expressions to EJBQL</h2></div></div></div><p> |
| <a class="link" href="queries.html#ejbqlquery" title="EJBQLQuery">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><pre class="programlisting">String serial = ... |
| Expression e = Pkg.SERIAL.eq(serial); |
| List<Object> params = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> ArrayList<Object>(); |
| EJBQLQuery query = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> EJBQLQuery(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"SELECT p FROM Pkg p WHERE "</span> + e.toEJBQL(params,<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"p"</span>); |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">for</span>(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">int</span> i=<span xmlns="http://www.w3.org/1999/xhtml" class="hl-number">0</span>;i<params.size();i++) { |
| query.setParameter(i+<span xmlns="http://www.w3.org/1999/xhtml" class="hl-number">1</span>, params.get(i)); |
| }</pre><p> |
| This would be equivalent to the following purely EJBQL querying logic; |
| </p><pre class="programlisting">EJBQLQuery query = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> EJBQLQuery(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"SELECT p FROM Pkg p WHERE p.serial = ?1"</span>); |
| query.setParameter(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-number">1</span>,serial);</pre><p> |
| </p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="persistent-objects-objectcontext.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="cayenne-guide-part2.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="orderings.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 6. Persistent Objects and ObjectContext </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 8. Orderings</td></tr></table></div></body></html> |