| <!DOCTYPE html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| |
| <!-- No caching headers --> |
| <meta http-equiv="cache-control" content="no-cache"/> |
| <meta http-equiv="pragma" content="no-cache"/> |
| <meta http-equiv="expires" content="-1"/> |
| <meta name="keywords" content="JDO, Apache, Java, Data, Objects"/> |
| <meta name="description" content="Apache JDO - Java Data Objects"/> |
| |
| <title>JDOQL Typed</title> |
| |
| <link rel="icon" type="image/png" href="images/JDOx150.png"/> |
| |
| <!-- |
| Apache JDO Documentation Template |
| ================================== |
| This template derived various aspects from Apache Deltaspike template, the Apache ISIS template and the Datanucleus template. |
| This template uses |
| * Bootstrap v3.3.7 (https://getbootstrap.com/) for navbar. |
| * Asciidoctor "foundation" CSS |
| * Bootswatch "cosmo" theme for Bootstrap (https://bootswatch.com/cosmo). |
| * Bootstrap TOC plugin v0.4.1 (https://afeld.github.io/bootstrap-toc/) for the table of contents. |
| * jQuery (necessary for Bootstrap's JavaScript plugins) |
| * Font-Awesome for some icons used by Asciidoctor |
| NOTE: tried using Font-Awesome CSS hosted locally but then fails to work! |
| --> |
| <link href="css/bootswatch/3.3.7/bootstrap-cosmo.css" rel="stylesheet"/> |
| <link href="css/bootstrap-toc/0.4.1/bootstrap-toc.min.css" rel="stylesheet"/> |
| |
| <link href="css/asciidoctor/foundation.css" rel="stylesheet"/> |
| <link href="css/datanucleus_theme.css" rel="stylesheet"/> |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> |
| <script src="js/bootstrap/3.3.7/bootstrap.min.js"></script> |
| <script src="js/bootstrap-toc/0.4.1/bootstrap-toc.min.js"></script> |
| |
| <!-- Coderay syntax formatter --> |
| <style type="text/css"> |
| /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */ |
| pre.CodeRay{background:#f7f7f8} |
| .CodeRay .line-numbers{border-right:1px solid currentColor;opacity:.35;padding:0 .5em 0 0} |
| .CodeRay span.line-numbers{display:inline-block;margin-right:.75em} |
| .CodeRay .line-numbers strong{color:#000} |
| table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none} |
| table.CodeRay td{vertical-align:top;line-height:inherit} |
| table.CodeRay td.line-numbers{text-align:right} |
| table.CodeRay td.code{padding:0 0 0 .75em} |
| .CodeRay .debug{color:#fff !important;background:#000080 !important} |
| .CodeRay .annotation{color:#007} |
| .CodeRay .attribute-name{color:#000080} |
| .CodeRay .attribute-value{color:#700} |
| .CodeRay .binary{color:#509} |
| .CodeRay .comment{color:#998;font-style:italic} |
| .CodeRay .char{color:#04d} |
| .CodeRay .char .content{color:#04d} |
| .CodeRay .char .delimiter{color:#039} |
| .CodeRay .class{color:#458;font-weight:bold} |
| .CodeRay .complex{color:#a08} |
| .CodeRay .constant,.CodeRay .predefined-constant{color:#008080} |
| .CodeRay .color{color:#099} |
| .CodeRay .class-variable{color:#369} |
| .CodeRay .decorator{color:#b0b} |
| .CodeRay .definition{color:#099} |
| .CodeRay .delimiter{color:#000} |
| .CodeRay .doc{color:#970} |
| .CodeRay .doctype{color:#34b} |
| .CodeRay .doc-string{color:#d42} |
| .CodeRay .escape{color:#666} |
| .CodeRay .entity{color:#800} |
| .CodeRay .error{color:#808} |
| .CodeRay .exception{color:inherit} |
| .CodeRay .filename{color:#099} |
| .CodeRay .function{color:#900;font-weight:bold} |
| .CodeRay .global-variable{color:#008080} |
| .CodeRay .hex{color:#058} |
| .CodeRay .integer,.CodeRay .float{color:#099} |
| .CodeRay .include{color:#555} |
| .CodeRay .inline{color:#000} |
| .CodeRay .inline .inline{background:#ccc} |
| .CodeRay .inline .inline .inline{background:#bbb} |
| .CodeRay .inline .inline-delimiter{color:#d14} |
| .CodeRay .inline-delimiter{color:#d14} |
| .CodeRay .important{color:#555;font-weight:bold} |
| .CodeRay .interpreted{color:#b2b} |
| .CodeRay .instance-variable{color:#008080} |
| .CodeRay .label{color:#970} |
| .CodeRay .local-variable{color:#963} |
| .CodeRay .octal{color:#40e} |
| .CodeRay .predefined{color:#369} |
| .CodeRay .preprocessor{color:#579} |
| .CodeRay .pseudo-class{color:#555} |
| .CodeRay .directive{font-weight:bold} |
| .CodeRay .type{font-weight:bold} |
| .CodeRay .predefined-type{color:inherit} |
| .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold} |
| .CodeRay .key{color:#808} |
| .CodeRay .key .delimiter{color:#606} |
| .CodeRay .key .char{color:#80f} |
| .CodeRay .value{color:#088} |
| .CodeRay .regexp .delimiter{color:#808} |
| .CodeRay .regexp .content{color:#808} |
| .CodeRay .regexp .modifier{color:#808} |
| .CodeRay .regexp .char{color:#d14} |
| .CodeRay .regexp .function{color:#404;font-weight:bold} |
| .CodeRay .string{color:#d20} |
| .CodeRay .string .string .string{background:#ffd0d0} |
| .CodeRay .string .content{color:#d14} |
| .CodeRay .string .char{color:#d14} |
| .CodeRay .string .delimiter{color:#d14} |
| .CodeRay .shell{color:#d14} |
| .CodeRay .shell .delimiter{color:#d14} |
| .CodeRay .symbol{color:#990073} |
| .CodeRay .symbol .content{color:#a60} |
| .CodeRay .symbol .delimiter{color:#630} |
| .CodeRay .tag{color:#008080} |
| .CodeRay .tag-special{color:#d70} |
| .CodeRay .variable{color:#036} |
| .CodeRay .insert{background:#afa} |
| .CodeRay .delete{background:#faa} |
| .CodeRay .change{color:#aaf;background:#007} |
| .CodeRay .head{color:#f8f;background:#505} |
| .CodeRay .insert .insert{color:#080} |
| .CodeRay .delete .delete{color:#800} |
| .CodeRay .change .change{color:#66f} |
| .CodeRay .head .head{color:#f4f} |
| </style> |
| </head> |
| <body data-spy="scroll" data-target="#toc"> |
| <!-- Navbar --> |
| <nav class="navbar navbar-default navbar-static-top"> |
| <div class="container"> |
| <div class="navbar-header"> |
| <!-- Three line menu button for use on mobile screens --> |
| <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| <!-- 'style' added to align image with navbar. FIX THIS --> |
| <a class="navbar-brand" href="https://db.apache.org/jdo/"> |
| <img style="margin-top: -12px;" alt="Brand" width="45.5" height="45.5" src="images/JDOx150.png"/> |
| </a> |
| <!-- TODO Any way to abstract the version from Maven? --> |
| <a class="navbar-brand" href="index.html">Apache JDO</a> |
| </div> |
| <!-- Navbar that will collapse on mobile screens --> |
| <div id="navbar" class="navbar-collapse collapse"> |
| <ul class="nav navbar-nav"> |
| <li class="dropdown"> |
| |
| <!-- menu item General --> |
| |
| |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">General<span class="caret"></span></a> |
| |
| <ul class="dropdown-menu"> |
| <li><a href="why_jdo.html">Why JDO?</a></li> |
| <li><a href="getting-started.html">Getting Started</a></li> |
| <li><a href="specifications.html">Specifications</a></li> |
| <li><a href="tck.html">TCK</a></li> |
| <li><a href="javadoc.html">API Javadoc</a></li> |
| <li role="separator" class="divider"></li> |
| <li><a href="jdo_v_jpa.html">JDO v JPA</a></li> |
| <li><a href="jdo_v_jpa_api.html">JDO v JPA : API</a></li> |
| <li><a href="jdo_v_jpa_orm.html">JDO v JPA : ORM</a></li> |
| <li role="separator" class="divider"></li> |
| <li><a href="license.html">License</a></li> |
| <li><a href="impls.html">Implementations</a></li> |
| <li><a href="jdo_3_0_overview.html">JDO 3.0 Overview</a></li> |
| <li><a href="references.html">References</a></li> |
| <li><a href="glossary.html">Glossary</a></li> |
| </ul> |
| </li> |
| |
| <!-- menu item API Usage --> |
| |
| <li class="dropdown"> |
| |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">API Usage<span class="caret"></span></a> |
| |
| <ul class="dropdown-menu"> |
| <li><a href="pmf.html">PersistenceManagerFactory</a></li> |
| <li><a href="pm.html">PersistenceManager</a></li> |
| <li><a href="transactions.html">Transactions</a></li> |
| <li><a href="attach_detach.html">Attach-Detach</a></li> |
| <li><a href="fetchgroups.html">Fetch Plan/Groups</a></li> |
| <li><a href="state_transition.html">Object States</a></li> |
| <li><a href="object_retrieval.html">Object Retrieval</a></li> |
| <li><a href="exceptions.html">Exceptions</a></li> |
| <li><a href="jdohelper.html">JDO Helper</a></li> |
| <li role="separator" class="divider"></li> |
| <li><a href="guides-replication.html">Data Replication</a></li> |
| </ul> |
| </li> |
| |
| <!-- menu item Types & Metadata --> |
| |
| <li class="dropdown"> |
| |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Types & Metadata<span class="caret"></span></a> |
| |
| <ul class="dropdown-menu"> |
| <li><a href="class_types.html">Types of Classes</a></li> |
| <li><a href="field_types.html">Types of Fields</a></li> |
| <li role="separator" class="divider"></li> |
| <!-- <li class="dropdown-header">Metadata</li> --> |
| <li><a href="metadata.html">MetaData</a></li> |
| <li><a href="annotations.html">Annotations</a></li> |
| <li><a href="jdo_dtd.html">jdo DTD/XSD</a></li> |
| <li><a href="orm_dtd.html">orm DTD/XSD</a></li> |
| <li><a href="jdoquery_dtd.html">jdoquery DTD/XSD</a></li> |
| <li><a href="jdoconfig_dtd.html">jdoconfig DTD/XSD</a></li> |
| <li role="separator" class="divider"></li> |
| <li><a href="enhancement.html">Bytecode Enhancement</a></li> |
| </ul> |
| </li> |
| |
| <!-- menu item Query --> |
| |
| <li class="dropdown"> |
| |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" style="background-color:#2385c6">Query<span class="caret"></span></a> |
| |
| <ul class="dropdown-menu"> |
| <li><a href="query_api.html">Query API</a></li> |
| <li role="separator" class="divider"></li> |
| <li><a href="jdoql.html">JDOQL</a></li> |
| <li><a href="jdoql_methods.html">Methods</a></li> |
| <li><a href="jdoql_result.html">Result</a></li> |
| <li><a href="jdoql_quickref.pdf">Quick Ref PDF</a></li> |
| <li><a href="jdoql_typed.html">JDOQL Typed API</a></li> |
| <li role="separator" class="divider"></li> |
| <li><a href="query_sql.html">SQL</a></li> |
| </ul> |
| </li> |
| |
| <!-- menu item Community --> |
| |
| <li class="dropdown"> |
| |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Community<span class="caret"></span></a> |
| |
| <ul class="dropdown-menu"> |
| <li><a href="get-involved.html">Get Involved</a></li> |
| <li><a href="team-list.html">Project Team</a></li> |
| <li><a href="mail-lists.html">Mailing Lists</a></li> |
| <li><a href="faq.html">FAQ</a></li> |
| </ul> |
| </li> |
| |
| <!-- menu item Development --> |
| |
| <li class="dropdown"> |
| |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Development<span class="caret"></span></a> |
| |
| <ul class="dropdown-menu"> |
| <li><a href="roadmap.html">RoadMap / TODO</a></li> |
| <li><a href="downloads.html">Downloads</a></li> |
| <li><a href="source-code.html">Source Code</a></li> |
| <li><a href="coding-standards.html">Coding Standards</a></li> |
| <li><a href="issuetracking.html">Issue Tracking</a></li> |
| </ul> |
| </li> |
| </ul> |
| <!-- 'style' added to fix height of input box. FIX THIS --> |
| <form class="navbar-form navbar-left" role="search" id="search-form" action="https://www.google.com/search" method="get" style="padding: 1px 15px;"> |
| <div class="form-group"> |
| <input name="sitesearch" value="db.apache.org/jdo" type="hidden"> |
| <input name="q" type="text" class="form-control" placeholder="Search" style="margin-top: 7px; padding: 1px; border-radius: 5px; height: 30px; vertical-align: middle;"> |
| </div> |
| </form> |
| </div> |
| </div> |
| </nav> |
| <div class="container"> |
| |
| <div class="row-fluid"> |
| <div class="col-sm-9"> |
| <!-- <div class="page-title"> |
| <h3>JDOQL Typed</h3> |
| </div> |
| --> |
| <div id="doc-content"> |
| <div class="sect1"> |
| <h2 id="JDOQLTyped">JDOQL Typed API</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>JDO 3.2 introduces a way of performing queries using a JDOQLTypedQuery API, that copes with refactoring of classes/fields. |
| The API follows the same <a href="jdoql.html">JDOQL</a> syntax that we have seen earlier in terms of the components of the query etc. |
| It produces queries that are much more elegant and simpler than the equivalent "Criteria" API in JPA.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="_preparation">Preparation</h3> |
| <div class="paragraph"> |
| <p>To set up your environment to use this JDOQLTypedQuery API you need to enable annotation processing, place your JDO 3.2 provider jars in your build path, |
| and specify a <code>@PersistenceCapable</code> annotation on your classes to be used in queries (you can still provide the remaining information in XML metadata if you wish to). |
| This annotation processor will (just before compile of your persistable classes), create a query metamodel "Q" class for each persistable class. |
| This is similar step to what QueryDSL requires, or indeed the JPA Criteria static metamodel.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="_using_maven">Using Maven</h4> |
| <div class="paragraph"> |
| <p>For example, using the JDO 3.2 RI, with Maven you need to have the following in your POM</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="xml"><span class="tag"><dependencies></span> |
| <span class="tag"><dependency></span> |
| <span class="tag"><groupId></span>org.datanucleus<span class="tag"></groupId></span> |
| <span class="tag"><artifactId></span>datanucleus-jdo-query<span class="tag"></artifactId></span> |
| <span class="tag"><version></span>5.0.9<span class="tag"></version></span> |
| <span class="tag"></dependency></span> |
| <span class="tag"><dependency></span> |
| <span class="tag"><groupId></span>javax.jdo<span class="tag"></groupId></span> |
| <span class="tag"><artifactId></span>jdo-api<span class="tag"></artifactId></span> |
| <span class="tag"><version></span>3.2<span class="tag"></version></span> |
| <span class="tag"></dependency></span> |
| ... |
| <span class="tag"></dependencies></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This creates the "metamodel" Q classes under <em>target/generated-sources/annotations/</em>. |
| You can change this location using the configuration property <strong>generatedSourcesDirectory</strong> of the <em>maven-compiler-plugin</em>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="_using_eclipse">Using Eclipse</h4> |
| <div class="paragraph"> |
| <p>With Eclipse you need to</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Go to <em>Java Compiler</em> and make sure the compiler compliance level is 1.8 or above</p> |
| </li> |
| <li> |
| <p>Go to <em>Java Compiler → Annotation Processing</em> and enable the project specific settings and enable annotation processing</p> |
| </li> |
| <li> |
| <p>Go to <em>Java Compiler → Annotation Processing → Factory Path</em>, enable the project specific settings and then add the following jars to the list: |
| <code>datanucleus-jdo-query.jar</code>, <code>jdo-api.jar</code></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>This creates the "metamodel" Q classes under <em>target/generated-sources/annotations/</em>. |
| You can change this location on the <em>Java Compiler → Annotation Processing</em> page.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="classes">Query Classes</h3> |
| <div class="paragraph"> |
| <p>The above preparation will mean that whenever you compile, the DataNucleus annotation processor (in <code>datanucleus-jdo-query.jar</code>) will generate a <strong>query class</strong> |
| for each model class that is annotated as persistable. So what is a <strong>query class</strong> you ask. |
| It is simply a mechanism for providing an intuitive API to generating queries. If we have the following model class</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@PersistenceCapable</span> |
| <span class="directive">public</span> <span class="type">class</span> <span class="class">Product</span> |
| { |
| <span class="annotation">@PrimaryKey</span> |
| <span class="type">long</span> id; |
| <span class="predefined-type">String</span> name; |
| <span class="type">double</span> value; |
| |
| ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>then the (generated) <strong>query class</strong> for this will be</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">QProduct</span> <span class="directive">extends</span> org.datanucleus.api.jdo.query.PersistableExpressionImpl<Product> |
| <span class="directive">implements</span> PersistableExpression<Product> |
| { |
| <span class="directive">public</span> <span class="directive">static</span> QProduct candidate(<span class="predefined-type">String</span> name) {...} |
| <span class="directive">public</span> <span class="directive">static</span> QProduct candidate() {...} |
| <span class="directive">public</span> <span class="directive">static</span> QProduct variable(<span class="predefined-type">String</span> name) {...} |
| <span class="directive">public</span> <span class="directive">static</span> QProduct parameter(<span class="predefined-type">String</span> name) {...} |
| |
| <span class="directive">public</span> NumericExpression<<span class="predefined-type">Long</span>> id; |
| <span class="directive">public</span> StringExpression name; |
| <span class="directive">public</span> NumericExpression<<span class="predefined-type">Double</span>> value; |
| |
| ... |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The generated class has the name of form <em>*Q*{className}</em>. |
| Also the generated class, by default, has a public field for each persistable field/property and is of a type <em>XXXExpression</em>. |
| These expressions allow us to give Java like syntax when defining your queries (see below). |
| So you access your persistable members in a query as <strong>candidate.name</strong> for example.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As mentioned above this is the default style of query class. However you can also create it in <em>property</em> style, |
| where you access your persistable members as <strong>candidate.name()</strong> for example. |
| The benefit of this approach is that if you have 1-1, N-1 relationship fields then it only initialises the members when called, whereas in the <em>field</em> |
| case above it has to initialise all in the constructor, so at static initialisation.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| The JDOQL Typed query mechanism only works for classes that are annotated, and not for classes that use XML metadata. |
| This is due to the fact that it makes use of a Java <em>annotation processor</em>. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="sect3"> |
| <h4 id="_limitations">Limitations</h4> |
| <div class="paragraph"> |
| <p>There are some corner cases where the use of expressions and this API may require casting to allow the full range of operations for JDOQL. Some examples</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>If you have a List field and call <code>ListExpression.get(position)</code> this returns an <code>Expression</code> rather than a specific <code>NumericExpression</code>, <code>StringExpression</code>, or whatever subtype. |
| You would need to cast the result to do subsequent calls.</p> |
| </li> |
| <li> |
| <p>If you have a Map field and call <code>MapExpression.get(key)</code> this returns an <code>Expression</code> rather than a specific <code>NumericExpression</code>, <code>StringExpression</code>, or whatever subtype. |
| You would need to cast the result to do subsequent calls.</p> |
| </li> |
| <li> |
| <p>If you have a Collection parameter and call <code>CollectionParameter.contains(fieldExpression)</code> then you may need to cast the <code>fieldExpression</code> to <code>Expression</code> |
| since the <code>CollectionParameter</code> will not have adequate java generic information for the compiler to do it automatically</p> |
| </li> |
| <li> |
| <p>If you have a Map parameter and call <code>MapParameter.contains(fieldExpression)</code> then you may need to cast the <code>fieldExpression</code> to <code>Expression</code> |
| since the <code>MapParameter</code> will not have adequate java generic information for the compiler to do it automatically</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="filter">Filtering</h3> |
| <div class="paragraph"> |
| <p>Let’s provide a sample usage of this query API. |
| We want to construct a query for all products with a value below a certain level, and where the name starts with "Wal". |
| So a typical query in a JDO-enabled application</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">pm = pmf.getPersistenceManager(); |
| |
| JDOQLTypedQuery<Product> tq = pm.newJDOQLTypedQuery(Product.class); |
| QProduct cand = QProduct.candidate(); |
| <span class="predefined-type">List</span><Product> results = tq.filter(cand.value.lt(<span class="float">40.00</span>).and(cand.name.startsWith(<span class="string"><span class="delimiter">"</span><span class="content">Wal</span><span class="delimiter">"</span></span>))) |
| .executeList();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This equates to the single-string query</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>SELECT FROM mydomain.Product WHERE this.value < 40.0 && this.name.startsWith("Wal")</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>As you see, we create a parametrised query, and then make use of the <strong>query class</strong> to access the candidate, |
| and from that make use of its fields, and the various Java methods present for the types of those fields. |
| Note that the API is <em>fluent</em>, meaning you can chain calls easily.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="order">Ordering</h3> |
| <div class="paragraph"> |
| <p>We want to order the results of the previous query by the product name, putting nulls first.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">tq.orderBy(cand.name.asc().nullsFirst());</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This query now equates to the single-string query</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>SELECT FROM mydomain.Product WHERE this.value < 40.0 && this.name.startsWith("Wal") ORDER BY this.name ASCENDING NULLS FIRST</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If you don’t want to specify null positioning, simply omit the <code>nullsFirst()</code> call. Similarly to put nulls last then call <code>nullsLast()</code>.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="methods">Methods</h3> |
| <div class="paragraph"> |
| <p>In the above example you will have seen the use of some of the normal JDOQL methods. With the JDOQLTyped API these are available on the different types of expressions. |
| For example, <em>cand.name</em> is a <code>StringExpression</code> and consequently it has all of the normal String methods available, just like in JDOQL and just like in Java. |
| Similarly if we had a class <code>Inventory</code> which had a Collection of <code>Product</code>, then we could use the method <strong>contains</strong> on the <code>CollectionExpression</code>.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| The JDOQL methods <em>JDOHelper.getObjectId</em> and <em>JDOHelper.getVersion</em> are available on <code>PersistableExpression</code>, for the object that they would be invoked on. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| The JDOQL methods <em>Math.{xxx}</em> are available on <code>NumericExpression</code>, for the numeric that they would be invoked on. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="result">Results</h3> |
| <div class="paragraph"> |
| <p>Let’s take the query in the above example and return the name and value of the Products only</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">JDOQLTypedQuery<Product> tq = pm.newJDOQLTypedQuery(Product.class); |
| QProduct cand = QProduct.candidate(); |
| <span class="predefined-type">List</span><<span class="predefined-type">Object</span><span class="type">[]</span>> results = tq.filter(cand.value.lt(<span class="float">40.00</span>).and(cand.name.startsWith(<span class="string"><span class="delimiter">"</span><span class="content">Wal</span><span class="delimiter">"</span></span>))).orderBy(cand.name.asc()) |
| .result(<span class="predefined-constant">false</span>, cand.name, cand.value).executeResultList();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This equates to the single-string query</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>SELECT this.name,this.value FROM mydomain.Product WHERE this.value < 40.0 && this.name.startsWith("Wal") ORDER BY this.name ASCENDING</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A further example using aggregates</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">JDOQLTypedQuery<Product> tq = pm.newJDOQLTypedQuery(Product.class); |
| <span class="predefined-type">Object</span> results = |
| tq.result(<span class="predefined-constant">false</span>, QProduct.candidate().value.max(), QProduct.candidate().value.min()).executeResultUnique();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This equates to the single-string query</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>SELECT max(this.value), min(this.value) FROM mydomain.Product</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If you wanted to assign an alias to a result component you do it like this</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">tq.result(<span class="predefined-constant">false</span>, cand.name.as(<span class="string"><span class="delimiter">"</span><span class="content">THENAME</span><span class="delimiter">"</span></span>), cand.value.as(<span class="string"><span class="delimiter">"</span><span class="content">THEVALUE</span><span class="delimiter">"</span></span>));</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="parameters">Parameters</h3> |
| <div class="paragraph"> |
| <p>It is important to note that JDOQLTypedQuery only accepts <strong>named</strong> parameters. |
| You obtain a named parameter from the JDOQLTypedQuery, and then use it in the specification of the filter, ordering, grouping etc. |
| Let’s take the query in the above example and specify the "Wal" in a parameter.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">JDOQLTypedQuery<Product> tq = pm.newJDOQLTypedQuery(Product.class); |
| QProduct cand = QProduct.candidate(); |
| <span class="predefined-type">List</span><Product> results = |
| tq.filter(cand.value.lt(<span class="float">40.00</span>).and(cand.name.startsWith(tq.stringParameter(<span class="string"><span class="delimiter">"</span><span class="content">prefix</span><span class="delimiter">"</span></span>)))) |
| .orderBy(cand.name.asc()) |
| .setParameter(<span class="string"><span class="delimiter">"</span><span class="content">prefix</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">Wal</span><span class="delimiter">"</span></span>).executeList();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This equates to the single-string query</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>SELECT FROM mydomain.Product WHERE this.value < 40.0 && this.name.startsWith(:prefix) ORDER BY this.name ASCENDING</pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="variables">Variables</h3> |
| <div class="paragraph"> |
| <p>Let’s try to find all Inventory objects containing a Product with a particular name. |
| This means we need to use a variable. Just like with a parameter, we obtain a <em>variable</em> from the Q class.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">JDOQLTypedQuery<Inventory> tq = pm.newJDOQLTypedQuery(Inventory.class); |
| QProduct <span class="type">var</span> = QProduct.variable(<span class="string"><span class="delimiter">"</span><span class="content">var</span><span class="delimiter">"</span></span>); |
| QInventory cand = QInventory.candidate(); |
| <span class="predefined-type">List</span><Inventory> results = tq.filter(cand.products.contains(<span class="type">var</span>).and(<span class="type">var</span>.name.startsWith(<span class="string"><span class="delimiter">"</span><span class="content">Wal</span><span class="delimiter">"</span></span>))).executeList();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This equates to the single-string query</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">SELECT FROM mydomain.Inventory WHERE <span class="local-variable">this</span>.products.contains(<span class="type">var</span>) && <span class="type">var</span>.name.startsWith(<span class="string"><span class="delimiter">"</span><span class="content">Wal</span><span class="delimiter">"</span></span>)</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="ifthenelse">If-Then-Else</h3> |
| <div class="paragraph"> |
| <p>Let’s make use of an IF-THEN-ELSE expression to return the products based on whether they are "domestic" or "international" (in our case its just based on the "id")</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">JDOQLTypedQuery<Product> tq = pm.newJDOQLTypedQuery(Product.class); |
| QProduct cand = QProduct.candidate(); |
| IfThenElseExpression<<span class="predefined-type">String</span>> ifElseExpr = tq.ifThenElse(<span class="predefined-type">String</span>.class, cand.id.lt(<span class="integer">1000</span>), <span class="string"><span class="delimiter">"</span><span class="content">Domestic</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">International</span><span class="delimiter">"</span></span>); |
| tq.result(<span class="predefined-constant">false</span>, ifElseExpr); |
| <span class="predefined-type">List</span><<span class="predefined-type">String</span>> results = tq.executeResultList();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This equates to the single-string query</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">SELECT IF (<span class="local-variable">this</span>.id < <span class="integer">1000</span>) <span class="string"><span class="delimiter">"</span><span class="content">Domestic</span><span class="delimiter">"</span></span> ELSE <span class="string"><span class="delimiter">"</span><span class="content">International</span><span class="delimiter">"</span></span> FROM mydomain.Product</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="subquery">Subqueries</h3> |
| <div class="paragraph"> |
| <p>Let’s try to find all Products that have a value below the average of all Products. This means we need to use a subquery</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">JDOQLTypedQuery<Product> tq = pm.newJDOQLTypedQuery(Product.class); |
| QProduct cand = QProduct.candidate(); |
| TypesafeSubquery<Product> tqsub = tq.subquery(Product.class, <span class="string"><span class="delimiter">"</span><span class="content">p</span><span class="delimiter">"</span></span>); |
| QProduct candsub = QProduct.candidate(<span class="string"><span class="delimiter">"</span><span class="content">p</span><span class="delimiter">"</span></span>); |
| <span class="predefined-type">List</span><Product> results = tq.filter(cand.value.lt(tqsub.selectUnique(candsub.value.avg()))).executeList();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Note that where we want to refer to the candidate of the subquery, we specify the alias ("p") explicitly. |
| This equates to the single-string query</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>SELECT FROM mydomain.Product WHERE this.value < (SELECT AVG(p.value) FROM mydomain.Product p)</pre> |
| </div> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| When you are using a subquery and want to refer to the candidate (or field thereof) of the outer query in the subquery |
| then you would use <code>cand</code> in the above example (or a field of it as required). |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="candidates">Candidates</h3> |
| <div class="paragraph"> |
| <p>If you don’t want to query instances in the datastore but instead query a collection of candidate instances, you can do this by setting the candidates, like this</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="java">JDOQLTypedQuery<Product> tq = pm.newJDOQLTypedQuery(Product.class); |
| QProduct cand = QProduct.candidate(); |
| <span class="predefined-type">List</span><Product> results = tq.filter(cand.value.lt(<span class="float">40.00</span>)).setCandidates(myCandidates).executeList();</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="col-sm-3"> |
| <nav id="toc" data-spy="affix" data-toggle="toc"></nav> |
| </div> |
| </div> |
| |
| </div> |
| |
| <footer style="color:#fff; background-color:#222222; padding: 5px;"> |
| <div class="container"> |
| <div class="row" style="margin-top:25px"> |
| <div class="col-sm" align="center"> |
| <a href="https://www.facebook.com/JavaDataObjects" class="externalLink" title="Facebook">Facebook</a> |
| | |
| <a href="https://twitter.com/JavaDataObjects" class="externalLink" title="Twitter">Twitter</a> |
| | |
| <a href="http://wiki.apache.org/jdo" class="externalLink" title="Wiki">Wiki</a> |
| | |
| <a href="http://issues.apache.org/jira/secure/BrowseProject.jspa?id=10630" class="externalLink" title="Issue Tracker">Issue Tracker</a> |
| | |
| <a href="mail-lists.html" title="Mailing Lists">Mailing Lists</a> |
| | |
| <a href="api31/apidocs/index.html" title="Latest Javadocs">Latest Javadocs</a> |
| | |
| <a href="https://privacy.apache.org/policies/privacy-policy-public.html" title="Privacy Policy">Privacy Policy</a> |
| </div> |
| </div> |
| <p class="text-center" style="margin-top:16px">© 2005-2022 Apache Software Foundation. All Rights Reserved.</p> |
| </div> |
| </footer> |
| |
| </body> |
| </html> |