<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[jpql - JBay Solutions - The Dev Blog]]></title><description><![CDATA[JBay Solutions Development Blog on Java, Android, Play2 and others]]></description><link>http://blog.jbaysolutions.com/</link><generator>Ghost 0.7</generator><lastBuildDate>Wed, 16 Oct 2024 01:15:05 GMT</lastBuildDate><atom:link href="http://blog.jbaysolutions.com/tag/jpql/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[JPA 2 Tutorial - Queries with JPQL]]></title><description><![CDATA[<p>If you are following the tutorials here you must be dying to do some queries using JPA. So, before we go any further into other aspects of JPA, lets query the model! For this task, instead of using SQL we will be using the <strong>Java Persistence Query Language</strong> or also</p>]]></description><link>http://blog.jbaysolutions.com/2014/10/16/jpa-2-tutorial-queries-on-the-model/</link><guid isPermaLink="false">d2a1755a-9d21-4c5c-889b-2ef3b09f19ee</guid><category><![CDATA[java]]></category><category><![CDATA[jpa]]></category><category><![CDATA[eclipselink]]></category><category><![CDATA[mysql]]></category><category><![CDATA[jpql]]></category><dc:creator><![CDATA[Rui Pereira]]></dc:creator><pubDate>Thu, 16 Oct 2014 13:17:09 GMT</pubDate><content:encoded><![CDATA[<p>If you are following the tutorials here you must be dying to do some queries using JPA. So, before we go any further into other aspects of JPA, lets query the model! For this task, instead of using SQL we will be using the <strong>Java Persistence Query Language</strong> or also known as <strong>JPQL</strong>. Exciting, yes?</p>

<h3 id="sampleproject">Sample Project</h3>

<p>About the sample project provided: it is a Maven project, we do not require an App Server at this point and the database used is a MySQL database. Check the <a href="http://blog.jbaysolutions.com/jpa2-tutorials">JPA2 Tutorials</a> page for links of recommended software.</p>

<p>You can get the project at <a href="https://github.com/jbaysolutions/jpa2tut-queries">GitHub</a>.</p>

<h1 id="whatisandwhyusejpql">What is and Why use JPQL?</h1>

<p>Before going into what is <strong>JPQL</strong>, lets talk about <strong>SQL</strong>. SQL is a query language used for managing data in a relational database. It an <strong>ANSI</strong> and <strong>ISO standard</strong>, but if you try running a medium to high complexity SQL query in two different relational databases from two different vendors, you are in for a big surprise. Why is that? Because some vendors create specific dialects of the SQL language.</p>

<p>Now imagine for a second you have a big application that you just developed and deployed, which is using a specific relational database, and for some reason you decide to migrate your data to another relational database from a different vendor. Well, if you wrote your queries in SQL, you are well advised to go and double check all of your queries for correctness against the new dialect. </p>

<p><strong>JPQL</strong> to the rescue. <strong>JPQL</strong> is a query language, much like <strong>SQL</strong> (<em>syntax wise and all that</em>), but instead of querying over a relational database, it queries over the persistent schema of entities and relationships (<em>which is almost the same thing, but not quite!</em>). What this means is that, if the relational model of the new database is still represented by the schema of entities and relationships you have on your project, then your JPQL queries will be portable and will work as expected. Emphasys on <strong>Portability</strong>.</p>

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>  
<!-- Horizontal For Posts - Text Only -->  
<ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-1311169549359552" data-ad-slot="3316155422"></ins>
<script>  
(adsbygoogle = window.adsbygoogle || []).push({});
</script>  

<p><br></p>

<h1 id="selectstatements">Select Statements</h1>

<p>For our tutorial we'll use the model created for the <a href="http://blog.jbaysolutions.com/2011/09/19/jpa-2-relationships-onetomany/">One-To-Many Tutorial</a> but we will extend it a bit more:</p>

<p><img src="http://blog.jbaysolutions.com/content/images/2014/10/overview-2.png" alt="Database model"></p>

<p>You can get the MySQL Workbench file for this from the <em>model</em> folder of the sample project. Along with the Workbench file there is a <strong>SQL script</strong> that creates the model and adds a few entries to it so we can test our queries:</p>

<pre><code>INSERT INTO `jpa2tut-queries`.`company` (`name`, `address`, `created_year`) VALUES ('JBay Solutions', 'Somewhere in Portugal', 2009);
INSERT INTO `jpa2tut-queries`.`company` (`name`, `address`, `created_year`) VALUES ('JetBrains', 'Somewhere in Prague', 2000);
INSERT INTO `jpa2tut-queries`.`company` (`name`, `address`, `created_year`) VALUES ('Google', 'Somewhere in the US', 1998);
INSERT INTO `jpa2tut-queries`.`company` (`name`, `address`, `created_year`) VALUES ('Yahoo', 'Somewhere in the US',1994);
INSERT INTO `jpa2tut-queries`.`company` (`name`, `address`, `created_year`) VALUES ('MySQL', 'Somewhere in an Oracle Office', 1995);
</code></pre>

<p>Also, check the <strong>src/main/java</strong> folder of the project in order to check the Entity Objects we have. An understanding of these objects is core to understanding the <strong>JPQL</strong> code we will write next. </p>

<h2 id="asimpleselect">A Simple Select</h2>

<p>As you can see from the previous <strong>SQL</strong> bits, we have a few entries on the <em>company</em> table. Lets query for the list of those entries:</p>

<pre><code><b>SELECT</b> c <b>FROM</b> CompanyEntity <b>AS</b> c
</code></pre>

<p>At this point you should be going like: <em>Wait a second please... I understand this language!</em>. Like said before, JPQL is very much like the regular SQL, except that we perform queries on the <em>persistent schema of entities and relationships</em>. </p>

<p>Lets run this in Java. Check the files inside the <strong>src/test/java</strong> folder of the sample project. You should be looking for the <strong>QueryTesting.java</strong> file at the method <strong>testSimpleQuery</strong>:</p>

<pre><code>Query query = em.createQuery("<b>SELECT</b> c <b>FROM</b> CompanyEntity <b>AS</b> c");
for ( CompanyEntity ce : (List&lt;CompanyEntity&gt;)query.getResultList()) {
    System.out.println(" -> Company : " + ce.getName() );
}
</code></pre>

<p>We give it a run:  </p>

<pre><code>[...]
[EL Info]: connection: 2014-10-14 16:41:13.476 --ServerSession(1563886825)--file:/home/rui/projects/jpa2tut-queries/target/test-classes/_jpa2tut-test login successful
 -> Company : JBay Solutions
 -> Company : JetBrains
 -> Company : Google
 -> Company : Yahoo
 -> Company : MySQL
</code></pre>

<p>Simple, yes? We create a <strong><em>Query</em></strong> Object with the JPQL query and we call <strong><em>em.getResultList();</em></strong> . We cast the result to <strong><em>List&lt;CompanyEntity&gt;</em></strong> , because we know that <strong><em>getResultList()</em></strong> returns a <em>List</em> (it does) and we also know that the query we created returns objects of <strong><em>CompanyEntity</em></strong> type.</p>

<p>We can also restrict the number of results being returned from the Query, by modifying the JPQL query used. Imagine we want to return all the companies that are called "<strong>JBay Solutions</strong>":</p>

<pre><code>SELECT c FROM CompanyEntity AS c <b>WHERE</b> c.name='JBay Solutions'
</code></pre>

<p>And the code being (<em>testSimpleQueryWhere method</em>) :  </p>

<pre><code>Query query = em.createQuery("SELECT c FROM CompanyEntity AS c <b>WHERE c.name='JBay Solutions'</b>");
for ( CompanyEntity ce : (List&lt;CompanyEntity&gt;)query.getResultList()) {
    System.out.println(" -> Company : " + ce.getName() );
}
</code></pre>

<p>Give it a quick spin:</p>

<pre><code>[EL Info]: connection: 2014-10-14 16:54:56.972--ServerSession(1861307614)--file:/home/rui/projects/jpa2tut-queries/target/test-classes/_jpa2tut-test login successful
 -> Company : JBay Solutions

Process finished with exit code 0
</code></pre>

<p>At this point one should be able to make pretty simple, but very useful queries, but some issues stand out:</p>

<ul>
<li>We must be constantly <strong>casting the results</strong></li>
<li>All our queries until now <strong>allow no input</strong></li>
</ul>

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>  
<!-- Horizontal For Posts - Text Only -->  
<ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-1311169549359552" data-ad-slot="3316155422"></ins>
<script>  
(adsbygoogle = window.adsbygoogle || []).push({});
</script>  

<p><br></p>

<h2 id="entertypedquery">Enter TypedQuery</h2>

<p>In JPA2 a new type of Query object was introduced. The <strong>TypedQuery</strong>, which allows us to make a Query that is <em>Typed</em>. That is it, <em>TypedQuery extends Query</em>, allowing one to define straight away what is to be returned and avoid continuously Casting every single result. </p>

<p>Looking at our previous examples, we can modify them to use <strong>TypedQuery</strong> instead of <strong>Query</strong> by using an overloaded <strong><em>createQuery method</em></strong> from the <strong>EntityManager</strong> that also takes as a parameter the Type of the query result:</p>

<pre><code><b>TypedQuery&lt;CompanyEntity&gt;</b> query = em.createQuery("SELECT c FROM CompanyEntity AS c"<b>, CompanyEntity.class</b>);

<b>TypedQuery&lt;CompanyEntity&gt;</b> query = em.createQuery("SELECT c FROM CompanyEntity AS c WHERE c.name='JBay Solutions'"<b>, CompanyEntity.class</b>);
</code></pre>

<p>to perform the iteration now we do:  </p>

<pre><code>for (CompanyEntity ce : query.getResultList()) {
    System.out.println(" -> Company : " + ce.getName());
}
</code></pre>

<p>No casting, no nothing. For the complete code check both <em>testSimpleTypedQuery</em> and <em>testSimpleTypedQueryWhere</em> methods of the <em>QueryTesting.java</em> file on the test sources.</p>

<p>We still have the <strong>no input</strong> issue to work on. </p>

<h2 id="passinginputtothequeries">Passing Input to the Queries</h2>

<p>In a way, some examples we shown before could be easily modified in a way to allow inputs to be passed onto them. Check this out: </p>

<pre><code>String <b>inputName</b> = "JBay Solutions"; 
TypedQuery&lt;CompanyEntity&gt; query = em.createQuery("SELECT c FROM CompanyEntity AS c WHERE c.name='" + <b>inputName</b> + "'", CompanyEntity.class);
</code></pre>

<p>Can you spot the problem with this? Well, simple, if you want to perform this query several times with different inputs, then you need to continuously re-create a new Query object. Not counting the <strong>performance impact</strong> it will have, it also <strong>leads to the JPQL not being readable at all</strong>. Imagine a query like the one presented but with several <em>conditional expressions</em> on the <em>WHERE clause</em>. What a nightmare. </p>

<p>To avoid these situations we have in JPQL:</p>

<ul>
<li><strong>Named Parameters</strong></li>
<li><strong>Positional Paramenters</strong></li>
</ul>

<p>Constructing a Query with any of these types of dynamic parameters allows a Query to be reused (and therefore avoid constant instantiation of Query objects) and makes the JPQL query much more readable.</p>

<h3 id="namedparameters">Named Parameters</h3>

<p>Lets look at the following example (from <em>testSimpleTypedQueryWhereInputNamed</em> method):</p>

<pre><code>em.createQuery("SELECT c FROM CompanyEntity AS c WHERE <b>c.name=:nameParam</b>", CompanyEntity.class);
query.setParameter("<b>nameParam</b>", "JBay Solutions");
</code></pre>

<p>So, a named parameter is a parameter that is called out by name. It is defined using the <strong>:&lt; param_name ></strong> notation:</p>

<ul>
<li>They are defined using the "<strong>:</strong>" prefix</li>
<li>They are Case Sensitive</li>
<li><strong>$</strong> and <strong>_</strong> chars are allowed, </li>
<li><strong>?</strong> is not allowed.</li>
<li>They can be used more than once on the Query string</li>
<li>They must be SET to something on execution</li>
<li>There is a list of reserved identifiers that cannot be used. Some of these reserved identifiers are : <strong>SELECT</strong> , <strong>WHERE</strong>, <strong>GROUP</strong>, <strong>TRUE</strong>, and many more, but you get the gist. <strong><em>These reserved identifiers are case insensitive</em></strong>, and non can be used as a named parameter. </li>
</ul>

<p>The named parameters are then set on the Query using the <em>setParameter</em> method of the Query instance:</p>

<pre><code><b>query.setParameter</b>("<b>nameParam</b>", "JBay Solutions");
for (CompanyEntity ce : query.getResultList()) {
    System.out.println(" -> Company : " + ce.getName());
}
<b>query.setParameter</b>("<b>nameParam</b>", "Google");
for (CompanyEntity ce : query.getResultList()) {
    System.out.println(" -> Company : " + ce.getName());
}</code></pre>

<p>What happens if you don't set one of the parameters? You get an IllegalStateException:</p>

<pre><code>[...]
[EL Info]: connection: 2014-10-14 18:30:02.302--ServerSession(822392390)--file:/home/rui/projects/jpa2tut-queries/target/test-classes/_jpa2tut-test login successful

<b>java.lang.IllegalStateException</b>: Query argument nameParam not found in the list of parameters provided during query execution.
    at org.eclipse.persistence.internal.jpa.QueryImpl.processParameters(QueryImpl.java:498)
    [...]
</code></pre>

<h3 id="positionalparameter">Positional Parameter</h3>

<p>Lets look at the following example (from <em>testSimpleTypedQueryWhereInputNumbered</em> method):</p>

<pre><code>em.createQuery("SELECT c FROM CompanyEntity AS c WHERE <b>c.name=?1</b>", CompanyEntity.class);
query.setParameter(<b>1</b>, "JBay Solutions");
</code></pre>

<p>A positional parameter is defined using the <strong>?&lt; int ></strong> notation:</p>

<ul>
<li>The parameters are numbered starting with <b>1</b></li>
<li>Positional parameter can appear more than once in the Query string.</li>
<li>The order by which they are set is irrelevant</li>
</ul>

<p>So:</p>

<pre><code>query.setParameter(1, "JBay Solutions");
query.setParameter(2, "Google");
</code></pre>

<p>will return the same  as:</p>

<pre><code>query.setParameter(2, "Google");
query.setParameter(1, "JBay Solutions");
</code></pre>

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>  
<!-- Horizontal For Posts - Text Only -->  
<ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-1311169549359552" data-ad-slot="3316155422"></ins>
<script>  
(adsbygoogle = window.adsbygoogle || []).push({});
</script>  

<p><br></p>

<h1 id="usingmultipleentities">Using Multiple Entities</h1>

<p>Right, making JPQL queries that take into account several Entities is the next logical step. For that, take into account the following SQL script (that is part of the <strong><em>create-and-populate.sql</em></strong> file of the sample project):</p>

<pre><code>INSERT INTO `jpa2tut-queries`.`employee` (`name`, `address`, `idcompany`, `birthday`) VALUES ('Rui Pereira', 'Lisbon',1 , '1981-06-27' );
INSERT INTO `jpa2tut-queries`.`employee` (`name`, `address`, `idcompany`, `birthday`) VALUES ('Gustavo Santo', 'Peniche',1, '1979-12-19');
INSERT INTO `jpa2tut-queries`.`employee` (`name`, `address`, `idcompany`, `birthday`) VALUES ('Maxim Shafirov', 'St.Petersburg, Russia',2, '1970-06-01');
INSERT INTO `jpa2tut-queries`.`employee` (`name`, `address`, `idcompany`, `birthday`) VALUES ('Valentin Kipiatkov', 'St.Petersburg, Russia',2, '1975-06-01');
<i>[... many more entries]</i>
</code></pre>

<p>This simply adds a few Employees to the previously created Companies. Now we have <strong>JBay Solutions</strong> with two employees and <strong>JetBrains</strong> with also two employees, and the remaining companies with also two employess (<em>check file for the remaining entries</em>).</p>

<p>Lets create a JPQL query that returns the employees of a particular company:</p>

<pre><code>TypedQuery&lt;EmployeeEntity&gt; query =
    em.createQuery("SELECT employee FROM <b>CompanyEntity AS company</b>, <b>EmployeeEntity as employee</b> " +
    "WHERE <b>company.name=:name</b> " +
    "<b>AND employee.company = company</b>", EmployeeEntity.class);
</code></pre>

<p>Pretty simple, yes? </p>

<ul>
<li>On the <strong>FROM</strong> clause we define <strong>two Entities</strong> with <strong>two Identifiers</strong></li>
<li>we make use of a <strong>named parameter</strong></li>
<li>we make use of the <strong>AND logical operator</strong></li>
</ul>

<p>Remember we said that <em>JPQL perform queries on the persistent schema of entities and relationships</em>. EmployeeEntity has a <strong>ManyToOne Relationship</strong> defined to CompanyEntity, and therefore we can use that relationship in our JPQL queries. The relationship is defined like this:</p>

<pre><code>@ManyToOne
@JoinColumn(name = "idcompany", referencedColumnName = "idcompany")
private CompanyEntity company;
</code></pre>

<p>Therefore when we in JPQL do something like <code>employee.company = SOMETHING</code>, we call <code>employee.company</code> a <strong>Path Expression</strong>, and the result for this case should be pretty obvious, because the relationship maps to only one other Entity. We'll talk a bit more about <strong>Path Expressions</strong> in a bit.</p>

<p>Lets give a run at <em>testMultipleEntities1</em> method on the <em>QueryTesting.java</em>, which runs this query like this:</p>

<pre><code>query.setParameter("name", "JBay Solutions");
for (EmployeeEntity client : query.getResultList()) {
    System.out.println(" -&gt; Q1 : " + client.getName());
}

query.setParameter("name", "JetBrains");
for (EmployeeEntity client : query.getResultList()) {
    System.out.println(" -&gt; Q2 : " + client.getName());
}
</code></pre>

<p>And check the results:</p>

<pre><code>[EL Info]: connection: 2014-10-14 20:58:59.383--ServerSession(1268465323)--file:/home/rui/projects/jpa2tut-queries/target/test-classes/_jpa2tut-test login successful
 -&gt; Q1 : Rui Pereira
 -&gt; Q1 : Gustavo Santo
 -&gt; Q2 : Maxim Shafirov
 -&gt; Q2 : Valentin Kipiatkov
</code></pre>

<p>Perfect!</p>

<p>Now, on the other side of the relationship, we'll have a <strong>OneToMany Relationship</strong>, like this:</p>

<pre><code>@OneToMany(mappedBy = "company")
private Collection&lt;EmployeeEntity&gt; employeeCollection;
</code></pre>

<p>And using that collection there on a JPQL query is also possible, but not as shown before. When we write something like this <code>AND employee.company = company</code> , the <code>employee.company</code> part as we said before is called a <strong>Path Expression</strong>, and one of the rules of <strong>Path Expressions</strong> is that it cannot be created from another <strong>Path Expression</strong> that evaluates to a collection. Lost you all there? In order words, check this next example.</p>

<p>Take this bit of code <code>FROM EmployeeEntity as employee</code> , we could create these <strong>Path Expressions</strong> :</p>

<ul>
<li><strong>employee.name</strong> : <em>Evaluates to a String</em></li>
<li><strong>employee.id</strong> : <em>Evaluates to an int</em></li>
<li><strong>employee.address</strong> : <em>Evaluates to a String</em></li>
<li><strong>employee.company</strong> : <em>Evaluates to a Company object</em></li>
<li><strong>employee.company.id</strong> : <em>Evaluates to an int</em></li>
<li><strong>employee.company.name</strong> : <em>Evaluates to a String</em></li>
<li><strong>employee.company.address</strong> : <em>Evaluates to a String</em></li>
<li><strong>employee.company.employeeCollection</strong> : <em>Evaluates to a Collection</em></li>
</ul>

<p>So you see, we created <strong>Path Expressions</strong> from other path expression in the way that <code>employee.company.id</code> is created from the <code>employee.company</code> <strong>Path Expression</strong>. </p>

<p>Since we have that rule of not being able to create from <strong>Path Expressions</strong> that evaluate to Collections, we can't do the following :</p>

<ul>
<li><strong>employee.company.employeeCollection.id</strong> : <em>Illegal</em></li>
<li><strong>employee.company.employeeCollection.name</strong> : <em>Illegal</em></li>
<li><strong>employee.company.employeeCollection.address</strong> : <em>Illegal</em></li>
<li><strong>employee.company.employeeCollection.company</strong> : <em>Illegal</em></li>
</ul>

<p>But <strong>Path Expressions</strong> that evaluate to Collections can be very useful in other ways. Lets give it another try at writting a JPQL query that makes use of this to achieve that same goal as the previous one:</p>

<pre><code>TypedQuery&lt;EmployeeEntity&gt; query =
    em.createQuery("SELECT employee FROM <b>CompanyEntity AS company</b>, <b>EmployeeEntity as employee</b> " +
    "WHERE <b>company.name</b>=<b>:name</b> " +
    "AND <b>employee MEMBER OF company.employeeCollection</b> ", EmployeeEntity.class);
</code></pre>

<p>See what we did there?</p>

<ul>
<li>we made use of the <strong>MEMBER OF comparison operator</strong></li>
<li>and we have a working knowledge of what is a <strong>Path Expression</strong></li>
</ul>

<p>There are a few more rules regarding <strong>Path Expressions</strong>, but a working knowledge is quite enough. If you feel you must know these right now, please check the JPA 2 Final Spec, which can be found at the bottom of this post in the References section. </p>

<p>About the <strong>MEMBER OF comparison operator</strong>, there are quite a few comparison operators, like <strong>BETWEEN</strong>, <strong>IN</strong> , <strong>EMPTY</strong>, <strong>EXISTS</strong>, <strong>LIKE</strong>, <strong>IS NULL</strong> and your well known <strong>=</strong> , <strong>></strong>, <strong>&lt;</strong>, <strong>&lt;></strong>, <strong>&lt;=</strong>, and <strong>>=</strong> .</p>

<h2 id="thememberofoperator">The MEMBER OF operator</h2>

<p>The <strong>MEMBER OF</strong> operator is used to match or <strong>NOT</strong> the existence of <em>something</em> in a <em>Collection</em>. An example if we may :</p>

<pre><code><i>employee</i> <b>MEMBER OF</b> <i>company.employeeCollection</i>
</code></pre>

<p>The <em>employee</em> section is a <em>path expression</em> that evaluates to an entity. It could evaluate to a simple value (like for example <code>employee.id</code> does) or an object (like <code>employee.company</code>), these are allowed. </p>

<p>The <em>company.employeeCollection</em> section is a <em>path expression</em> that will evaluate to a Collection of Employees. That is it.</p>

<p>To match the inexistence of <em>something</em> inside a <em>Collection</em>, we can use the <strong>NOT MEMBER OF</strong>, like this:</p>

<pre><code><i>employee</i> <b>NOT MEMBER OF</b> <i>company.employeeCollection</i>
</code></pre>

<p>The <strong>NOT</strong> is a constant in the remaing comparison operators, like we will see next. </p>

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>  
<!-- Horizontal For Posts - Text Only -->  
<ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-1311169549359552" data-ad-slot="3316155422"></ins>
<script>  
(adsbygoogle = window.adsbygoogle || []).push({});
</script>  

<p><br></p>

<h2 id="thebetweenoperator">The BETWEEN operator</h2>

<p>Lets shift our focus now to the <em>Company</em> table and <em>CompanyEntity</em> bean. There is a field there that stores the year the Company was created. It is mapped as an Integer and cannot be Null. </p>

<p>For our next task we will write a JPQL query that will return the Companies that were created in 1995 or after and in 2005 or before:</p>

<pre><code>em.createQuery("SELECT company FROM CompanyEntity AS company " +
"WHERE company.<b>createdYear >= 1995</b> " +
"AND company.<b>createdYear <= 2005<="" b=""> ", CompanyEntity.class);
</=></b></code></pre>

<p>Easy, yes? But we could use the <strong>BETWEEN</strong> operator in the following way:</p>

<pre><code>"WHERE company.createdYear <b>BETWEEN</b> 1995 AND 2005 "</code></pre>

<p>Which will return the exact same result. <br>
Expanding on what we already know, we could actually just replace both the <strong>MIN</strong> and <strong>MAX</strong> arguments of the <strong>BETWEEN</strong> operator with named parameters and allow for them to be defined dynamically:</p>

<pre><code>query = em.createQuery("SELECT company FROM CompanyEntity AS company"+
"WHERE <b>company.createdYear BETWEEN :minimum AND :maximum</b> ", CompanyEntity.class);
query.setParameter("minimum", 1995);
query.setParameter("maximum", 2000);</code></pre>

<p>But <strong>BETWEEN</strong> can be used with other types of parameters, like <strong>Dates</strong>. Lets write a JPQL query that returns now all the Employees of any company that were born between 1979-01-01 and today:</p>

<pre><code>TypedQuery<employeeentity> query =
    em.createQuery("SELECT employee FROM EmployeeEntity AS employee"+
    "WHERE <b>employee.birthday BETWEEN :minimum AND :maximum</b> ", EmployeeEntity.class);
query.setParameter(<b>"minimum", "1979-01-01"</b>);
query.setParameter(<b>"maximum", new Date()</b>);
</employeeentity></code></pre>

<p>To get the exclusion of those dates, you use the NOT :</p>

<pre><code>"WHERE employee.birthday <b>NOT BETWEEN</b> :minimum AND :maximum ", EmployeeEntity.class);</code></pre>

<p>Moving on.</p>

<h2 id="thelikeoperator">The LIKE operator</h2>

<p>We know how to compare Strings, we have the regular <strong>=</strong> and <strong>&lt;></strong> comparison operators. Lets try them out in writing a JPQL query that returns all the companies that are named Google:</p>

<pre><code>SELECT company FROM CompanyEntity AS company WHERE  company.name = 'Google'
</code></pre>

<p>But what about if on our database, that company was named "google" and not "Google"? Well, that query would fail, that's what. </p>

<p>And what if we want to return all the Companies that have "oo" (two 'o's) in their name? Well then we have to write a pattern and check which entries match that pattern. </p>

<p>For that we use the <strong>LIKE</strong> operator.</p>

<p>The <strong>LIKE</strong> works like this : on the <strong>left hand side you place a String</strong> or a path expression that evaluates to a String. On the <strong>right hand side you place a String that has a pattern</strong> to be matched. </p>

<p>So, if we do:</p>

<pre><code>WHERE  company.name LIKE 'google'
</code></pre>

<p>We would get a match for companies named:</p>

<ul>
<li>google</li>
<li>Google</li>
<li>GOOGLE</li>
<li>GoOgLe</li>
</ul>

<p>In order words: 5 letter words that have the same letters in that order, but are case insensitive.</p>

<p>Lets write a JPQL that matches all Companies with "oo" in their name, no matter where in their name:</p>

<pre><code>WHERE company.name LIKE '%oo%' 
</code></pre>

<p>Here we go. Now we will match :</p>

<ul>
<li>Google</li>
<li>Yahoo</li>
<li>oo.org</li>
<li>Boo</li>
</ul>

<p>The <strong>%</strong> character is a wildcard character that matches any sequence of characters, including an emply one. The other wildcard charater we have is the underscore <strong>_</strong> which matches exactly one character.</p>

<p>So, if we were to write:</p>

<pre><code>WHERE company.name LIKE '%oo_'
</code></pre>

<p>We would only match companies named like this:</p>

<ul>
<li>Gooa</li>
<li>Goob</li>
<li>oox</li>
<li>ooy</li>
<li>yahooa</li>
</ul>

<p>Why? Because the <strong>_</strong> wildcard must match exactly 1 character, whatever character it is, but it must be 1!</p>

<p>As with the precious operator, if we want to get all the company names that don't match that pattern, we use the <strong>NOT</strong> :</p>

<pre><code>WHERE  company.name NOT LIKE '%oo%' 
</code></pre>

<p>And we get pretty much any company whose name doesn't have exactly two 'o's together. </p>

<h2 id="theemptyoperator">The EMPTY operator</h2>

<p>The <strong>EMPTY</strong> operator simply evaluates if Collection expressed by a <em>path expression</em> is empty, or <strong>NOT EMPTY</strong>. </p>

<p>Lets write a JPQL query that returns all the companies that have no employees:</p>

<pre><code>SELECT company FROM CompanyEntity AS company WHERE <b>company.employeeCollection IS EMPTY</b>
</code></pre>

<p>The <em>company.employeeCollection</em> poins to a Collection of Employees. If we run this query against our test database, we get no returns, because all the companies on our DB have employees. So instead lets have a query that returns all the companies that have employees:</p>

<pre><code>SELECT company FROM CompanyEntity AS company WHERE <b>company.employeeCollection IS NOT EMPTY</b>
</code></pre>

<p>And now if we run that query we get returned all the Companies in our test DB.</p>

<h2 id="thenulloperator">The NULL operator</h2>

<p>Not that any of the operators are difficult to understand, but <strong>NULL</strong> is by far the easiest one. <strong>IS NULL</strong> is used to test if a give <em>path expression</em> or parameter is a NULL value , or <strong>NOT</strong>. </p>

<p>For completeness' sake lets write a JPQL query that returns all Employees that have their address NULL:</p>

<pre><code>SELECT employee FROM EmployeeEntity AS employee WHERE  employee.address IS NULL
</code></pre>

<p>And now, a query that returns all the Employees that don't have their address NULL:</p>

<pre><code>SELECT employee FROM EmployeeEntity AS employee WHERE  employee.address IS NOT NULL
</code></pre>

<p>In case you are wondering, a <em>path expression</em> that evaluates to a <strong>Collection cannot be NULL</strong>. It can however be <strong>EMPTY</strong> or <strong>NOT EMPTY</strong>. So, if you try something like this:</p>

<pre><code>SELECT company FROM CompanyEntity AS company WHERE  company.employeeCollection IS NULL
</code></pre>

<p>Well... that just isn't going to work.</p>

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>  
<!-- Horizontal For Posts - Text Only -->  
<ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-1311169549359552" data-ad-slot="3316155422"></ins>
<script>  
(adsbygoogle = window.adsbygoogle || []).push({});
</script>  

<p><br></p>

<h1 id="butthereismore">But there is more!</h1>

<p>What about Subqueries? Any more comparision operators? And Update and Delete statements? What about the Criteria API? </p>

<p>We'll take a break here, because this post is getting big and we'll continue on the next post! We'll update this one with a link as soon as the next post comes out.</p>

<h1 id="references">References</h1>

<p><a href="http://download.oracle.com/otndocs/jcp/persistence-2.0-fr-oth-JSpec/">JPA 2 Final Spec</a></p>]]></content:encoded></item></channel></rss>