JPA Queries and Tips

20

Posted on April 20, 2012 by

Share it now!

JPA: NamedQuery, querying with dates, warnings about the getSingleResult method

To avoid the repetition of queries codes, upgrade the performance and make easier to maintain the queries we can use the NamedQueries. A NamedQuery uses JPQL as syntax and it is declared in the entity class. It is easier to edit the query after an update in the class code.

If you want to do a query using a date as parameter you can send only the date object or you can pass an enum that will describe the date type (recommended).

Bellow you will see how to create and use a @NamedQuery and how to query with date:

package com.model;

import java.util.Date;

import javax.persistence.*;

@Entity
@NamedQuery(name="Dog.FindByDateOfBirth", query="select d from Dog d where d.dateOfBirth = :dateOfBirth")
public class Dog {

	public static final String FIND_BY_DATE_OF_BIRTH = "Dog.FindByDateOfBirth";

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;

	// get and set
}
package com.model;

import java.util.*;

import javax.persistence.*;

@Entity
@NamedQueries({
		@NamedQuery(name="Person.findByName", query="select p from Person p where p.name = :name"),
		@NamedQuery(name="Person.findByAge", query="select p from Person p where p.age = :age")})
})
public class Person {

	public static final String FIND_BY_NAME = "Person.findByName";
	public static final String FIND_BY_AGE = "Person.findByAge";

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;

        // get and set

}
package com.main;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TemporalType;

import com.model.Dog;
import com.model.Person;

public class Page07 {
	public static void main(String[] args) {
		CodeGenerator.startConnection();

		CodeGenerator.generateData();

		EntityManager em = CodeGenerator.getEntityManager();

		int age = 70;
		List<Person> personByAge = getPersonByAge(em, 70);
		System.out.println("Found " + personByAge.size() + " person(s) with the age of: " + age);

		SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
		Date dateOfBirth = null;
		try {
			dateOfBirth = formatter.parse("10/1/1995");
		} catch (ParseException e) {
			e.printStackTrace();
		}

		List<Dog> dogsByDayOfBirth = getDogsByDayOfBirth(em, dateOfBirth);
		System.out.println("Found " + dogsByDayOfBirth.size() + " dog with birth date of " + formatter.format(dateOfBirth));

		/*
		 * This queries will raise Runtime Exceptions
		 *
		 * em.createQuery("select p from Person p").getSingleResult(); // NonUniqueResultException
		 *
		 * em.createQuery("select p from Person p where p.name = 'JJJJ'").getSingleResult(); //NoResultException
		 */

		CodeGenerator.closeConnection();
	}

	@SuppressWarnings("unchecked")
	private static List<Dog> getDogsByDayOfBirth(EntityManager em, Date dateOfBirth) {
		Query query = em.createNamedQuery(Dog.FIND_BY_DATE_OF_BIRTH);
		query.setParameter("dateOfBirth", dateOfBirth, TemporalType.DATE);

		return query.getResultList();
	}

	@SuppressWarnings("unchecked")
	private static List<Person> getPersonByAge(EntityManager em, int age) {
		Query query = em.createNamedQuery(Person.FIND_BY_AGE);
		query.setParameter("age", age);

		return query.getResultList();
	}
}

About the code above:

  • If you have only one query you can use the @NamedQuery annotation; if you have more than one query you can use the @NamedQueries annotations.
  • When you do a query using a date object you can also use the TemporalType enum to detail the type of the date. For date queries you can use “java.util.Date” or “java.util.GregorianCalendar”.

getSingleResult()

Be careful when you use this method. It has a special way to handle two behaviors that it is easy to happen and both behaviors will raise an exception:

  • Find more than one object from the query result: NonUniqueResultException
  • Find no result: NoResultException

You always need to use a try/catch to avoid these exceptions to be thrown in the production environment.

If you want to see this exceptions in real time, in the code above you can find two commented queries; it will raise the exceptions bellow:

Exception in thread "main" <span style="text-decoration: underline;">javax.persistence.NonUniqueResultException</span>: result returns more than one elements
at org.hibernate.ejb.QueryImpl.getSingleResult(<span style="text-decoration: underline;">QueryImpl.java:287</span>)
Exception in thread "main" <span style="text-decoration: underline;">javax.persistence.NoResultException</span>: No entity found for query
at org.hibernate.ejb.QueryImpl.getSingleResult(<span style="text-decoration: underline;">QueryImpl.java:280</span>)

Response to JPA Queries and Tips

    • uaihebert Post author

      Hello, good afternoon.

      Some people around the world are reporting some problems about the source code.

      The code is hosted on google, maybe this is the problem.

      In the last page of this post I provided other link that you can use.

      Thanks for the feedback.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current day month ye@r *