Queries are represented in JPA 2 by two interfaces - the old Query interface, which was the only interface available for representing queries in JPA 1, and the new TypedQuery interface that was introduced in JPA 2. The TypedQuery interface extends the Query interface.
In JPA 2 the Query interface should be used mainly when the query result type is unknown or when a query returns polymorphic results and the lowest known common denominator of all the result objects is Object. When a more specific result type is expected queries should usually use the TypedQuery interface. It is easier to run queries and process the query results in a type safe manner when using the TypedQuery interface.
Ngoài query thông thường dùng Query hoặc TypedQuery thì còn có JPA Criteria API  và named queries 

Building Queries with createQuery

As with most other operations in JPA, using queries starts with an EntityManager (represented by em in the following code snippets), which serves as a factory for both Query and TypedQuery:
  Query q1 = em.createQuery("SELECT c FROM Country c");
 
  TypedQuery<Country> q2 =
      em.createQuery("SELECT c FROM Country c", Country.class);

In the above code, the same JPQL query which retrieves all the Country objects in the database is represented by both q1 and q2. When building a TypedQuery instance the expected result type has to be passed as an additional argument, as demonstrated for q2. Because, in this case, the result type is known (the query returns only Country objects), a TypedQuery is preferred.
There is another advantage of using TypedQuery in ObjectDB. In the context of the queries above, if there are no Country instances in the database yet and the Country class is unknown as a managed entity class - only the TypedQuery variant is valid because it introduces the Countryclass to ObjectDB.

Dynamic JPQL, Criteria API and Named Queries

Building queries by passing JPQL query strings directly to the createQuery method, as shown above, is referred to in JPA as dynamic query construction because the query string can be built dynamically at runtime.
The JPA Criteria API provides an alternative way for building dynamic queries,  based on Java objects that represent query elements (replacing string based JPQL).
JPA also provides a way for building static queries, as named queries, using the @NamedQuery and @NamedQueries annotations. It is considered to be a good practice in JPA to prefer named queries over dynamic queries when possible.

Ordinary Query Execution (with getResultList)

The following query retrieves all the Country objects in the database. Because multiple result objects are expected, the query should be run using the getResultList method:
  TypedQuery<Country> query =
      em.createQuery("SELECT c FROM Country c", Country.class);
  List<Country> results = query.getResultList();
Both Query and TypedQuery define a getResultList method, but the version of Query returns a result list of a raw type (non generic) instead of a parameterized (generic) type:
  Query query = em.createQuery("SELECT c FROM Country c");
  List results = query.getResultList();

Single Result Query Execution (with getSingleResult)

The getResultList method (which was discussed above) can also be used to run queries that return a single result object. In this case, the result object has to be extracted from the result collection after query execution (e.g. by results.get(0)). To eliminate this routine operation JPA provides an additional method, getSingleResult, as a more convenient method when exactly one result object is expected.
The following aggregate query always returns a single result object, which is a Long object reflecting the number of Country objects in the database:
  TypedQuery<Long> query = em.createQuery(
      "SELECT COUNT(c) FROM Country c", Long.class);
  long countryCount = query.getSingleResult();
Notice that when a query returns a single object it might be tempting to prefer Query over TypedQuery even when the result type is known because the casting of a single object is easy and the code is simple:
  Query query = em.createQuery("SELECT COUNT(c) FROM Country c");
  long countryCount = (Long)query.getSingleResult();

  Query query2 = em.createQuery("SELECT MAX(c.population) FROM Country c");
  long countryPopulation = (Long)query.getSingleResult();
An aggregate COUNT query always returns one result, by definition.
In other cases our expectation for a single object result might fail, depending on the database content. For example, the following query is expected to return a single Country object:
  Query query = em.createQuery(
      "SELECT c FROM Country c WHERE c.name = 'Canada'");
  Country c = (Country)query.getSingleResult();
However, the correctness of this assumption depends on the content of the database. If the database contains multiple Country objects with the name 'Canada' (e.g. due to a bug) a NonUniqueResultException is thrown. On the other hand, if there are no results at all a NoResultException is thrown. Therefore, using getSingleResult requires some caution and if there is any chance that these exceptions might be thrown they have to be caught and handled.
Query parameters enable the definition of reusable queries. Such queries can be executed with different parameter values to retrieve different results. Running the same query multiple times with different parameter values (arguments) is more efficient than using a new query string for every query execution, because it eliminates the need for repeated query compilations.

Named Parameters (:name)

The following method retrieves a Country object from the database by its name:
  public Country getCountryByName(EntityManager em, String name) {
    TypedQuery<Country> query = em.createQuery(
        "SELECT c FROM Country c WHERE c.name = :name", Country.class);
    return query.setParameter("name", name).getSingleResult();
  } 

Query query = em.createQuery("SELECT e FROM Employee e 
      WHERE e.firstName = :first and e.lastName = :last");
query.setParameter("first", "Bob");
query.setParameter("last", "Smith");
List<Employee> = query.getResultList();
The WHERE clause reduces the query results to Country objects whose name field value is equal to :name, which is a parameter that serves as a placeholder for a real value. Before the query can be executed a parameter value has to be set using the setParameter method. The setParametermethod supports method chaining (by returning the same TypedQuery instance on which it was invoked), so invocation of getSingleResult can be chained to the same expression.
Named parameters can be easily identified in a query string by their special form, which is a colon (:) followed by a valid JPQL identifier that serves as the parameter name. JPA does not provide an API for defining the parameters explicitly (except when using criteria API), so query parameters are defined implicitly by appearing in the query string. The parameter type is inferred by the context. In the above example, a comparison of :name to a field whose type is Stringindicates that the type of :name itself is String.
Queries can include multiple parameters and each parameter can have one or more occurrences in the query string. A query can be run only after setting values for all its parameters (in no matter in which order).

Ordinal Parameters (?index)

In addition to named parameter, whose form is :name, JPQL supports also ordinal parameter, whose form is ?index. The following method is equivalent to the method above, except that an ordinal parameter replaces the named parameter:
  public Country getCountryByName(EntityManager em, String name) {
    TypedQuery<Country> query = em.createQuery(
        "SELECT c FROM Country c WHERE c.name = ?1", Country.class);
    return query.setParameter(1, name).getSingleResult();
  } 
The form of ordinal parameters is a question mark (?) followed by a positive int number. Besides the notation difference, named parameters and ordinal parameters are identical.
Named parameters can provide added value to the clarity of the query string (assuming that meaningful names are selected). Therefore, they are preferred over ordinal parameters.

Positional parameter query example (?)

Positional parameter query example:
  Query query = em.createQuery("SELECT e FROM Employee e 
        WHERE e.firstName = ? and e.lastName = ?");
  query.setParameter(1, "Bob");
  query.setParameter(2, "Smith");
  List<Employee> = query.getResultList(); 
The form of positional parameters is a question mark (?) .

Criteria Query Parameters

In a JPA query that is built by using the JPA Criteria API - parameters (as other query elements) are represented by objects (of type ParameterExpression or its super interface Parameter) rather than by names or numbers.
See the Parameters in Criteria Queries section for more details.

Parameters vs. Literals

Following is a third version of the same method. This time without parameters:
  public Country getCountryByName(EntityManager em, String name) {
    TypedQuery<Country> query = em.createQuery(
        "SELECT c FROM Country c WHERE c.name = '" + name + "'",
        Country.class);
    return query.getSingleResult();
  } 
Instead of using a parameter for the queried name the new method embeds the name as a String literal. There are a few drawbacks to using literals rather than parameters in queries.
First, the query is not reusable. Different literal values lead to different query strings and each query string requires its own query compilation, which is very inefficient. On the other hand, when using parameters, even if a new TypedQuery instance is constructed on every query execution, ObjectDB can identify repeating queries with the same query string and use a cached compiled query program, if available.
Second, embedding strings in queries is unsafe and can expose the application to JPQL injection attacks. Suppose that the name parameter is received as an input from the user and then embedded in the query string as is. Instead of a simple country name, a malicious user may provide JPQL expressions that change the query and may help in hacking the system.
In addition, parameters are more flexible and support elements that are unavailable as literals, such as entity objects.

API Parameter Methods

Over half of the methods in Query and TypedQuery deal with parameter handling. The Queryinterface defines 18 such methods, 9 of which are overridden in TypedQuery. That large number of methods is not typical to JPA, which generally excels in its thin and simple API.
There are 9 methods for setting parameters in a query, which is essential whenever using query parameters. In addition, there are 9 methods for extracting parameter values from a query. These get methods, which are new in JPA 2, are expected to be much less commonly used than the set methods.
Two set methods are demonstrated above - one for setting a named parameter and the other for setting an ordinal parameter. A third method is designated for setting a parameter in a Criteria API query. The reason for having nine set methods rather than just three is that JPA additionally provides three separate methods for setting Date parameters as well as three separate methods for setting Calendar parameters.
Date and Calendar parameter values require special methods in order to specify what they represent, such as a pure date, a pure time or a combination of date and time, as explained in detail in the Date and Time (Temporal) Types section.
For example, the following invocation passes a Date object as a pure date (no time):
query.setParameter("date", new java.util.Date(), TemporalType.DATE);
Since TemporalType.Date represents a pure date, the time part of the newly constructed java.util.Date instance is discarded. This is very useful in comparison against a specific date, when time should be ignored.
The get methods support different ways to extract parameters and their values from a query, including by name (for named parameter), by position (for ordinal parameters) by Parameter object (for Criteria API queries), each with or without an expected type. There is also a method for extracting all the parameters as a set (getParameters) and a method for checking if a specified parameter has a value (isBound). These methods are not required for running queries and are expected to be less commonly used.