Dynamic Named Query in Entity class using JPQL example - java

I have a named query as below;
#NamedQuery(name = "MyEntityClass.findSomething", query = "SELECT item FROM MyTable mytbl")
Now I want to append dynamic sort clause to this query (based on UI parameters)
Can I get an example using JPQL for doing the same (like how to set a dynamic ORDER BY in the Entity class)
I have already tried using CriteriaQuery, but was looking for a JPQL implementation now.

NamedQueries are by definition NOT dynamic, it is not correct to change them programmatically.
So the way to go is to create a JPQL query (but not a named query) like this:
TypedQuery<MyEntity> query = em.createdQuery("SELECT item FROM MyEntity item ORDER BY "+sortingCol, MyEntity.class);
On the other hand, if you REALLY want to use the named query, you could do that the following way:
#NamedQuery(name = "MyEntityClass.findSomething", query = MyEntity.NAMED_QUERY)
#Entity
public class MyEntity {
public static final NAMED_QUERY= "SELECT item FROM MyTable mytbl";
//+your persistent fields/properties...
}
//and later in your code
TypedQuery<MyEntity> query = entityManager.createQuery(MyEntity.NAMED_QUERY + " ORDER BY " + sortingCol, MyEntity.class);

Complementing for JPA 2.1
As of JPA 2.1 it is possible to define named queries programmatically.
This can be achieved using entityManagerFactory.addNamedQuery(String name, Query).
Example:
Query q = this.em.createQuery("SELECT a FROM Book b JOIN b.authors a WHERE b.title LIKE :title GROUP BY a");
this.em.getEntityManagerFactory().addNamedQuery("selectAuthorOfBook", q);
// then use like any namedQuery
Reference here
This can be useful, for instance, if you have the orderby field defined as a application parameter. So, when the application starts up or on the first run of the query, you could define the NamedQuery with the defined OrderBy field.
On the other side, if your OrderBy can be changed anytime (or changes a lot), then you need dynamic queries instead of NamedQuery (static). It would not worth to (re)create a NamedQuery every time (by performance).

#NamedQuery
Persistence Provider converts the named queries from JPQL to SQL at deployment time.
Until now, there is no feature to create/update the query with #NamedQuery annotation at runtime.
On the other hand, you can use Reflection API, to change the annotation value at runtime. I think It is not solution, also it is not you wanted .
em.createQuery()
Persistence Provider converts the dynamic queries from JPQL to SQL every time it is invoked.
The main advantage of using dynamic queries is that the query can be created based on the user inputs.

Related

Execute dynamic query with Spring Data JPA

#Query(value = "SELECT * FROM H4 WHERE 1")
List getResult();
Instead of the query "SELECT * FROM H4 WHERE 1" I want to put a String variable containing query generated elsewhere.
#Query, like any other annotation, uses a compile time constant to define attributes. You can't define it's value in runtime unless you plan to hack the Spring Data JPA framework.
You should use either Specifications with criteria, Query by example or JPQL to define and execute your dynamic query.
Create constants and set the value as below.
#Query(value = ApplicationConstantClass.QUERY_STRING_CONSTANT)
List getResult();
or Use EntityManager or SessionFactory of hibernate to execute dynamically generated query.

JPA NamedQuery Select specific column and return class type

I am using JPA, I have the basic named query like this
#NamedQuery(name="Manifest.findAll", query="SELECT m FROM Manifest m")
When I call this,
entityManager.createNamedQuery("Manifest.getManifestInfo").getResultList()
I get the object back in a list like this
[{id:"1", name:"foo"},{id:"2", name:"bar"}]
But then I have another named query where I just get the names
#NamedQuery(name="Manifest.getManifestName", query="SELECT m.name FROM Manifest m")
When I run that query I get
[["foo"],["bar"]]
How can I get the second query to return the object type so its liek
[{name:"foo"},{name:"bar"}]
I made this simpler to show what I am trying to do here, the actual table has more columns but it is the same principal.
How can I return the object type?
The feature for that use case in JPA is an Entity Graph.
Define it on your entity like this:
#NamedEntityGraph(name="nameOnly", attributeNodes={
#NamedAttributeNode("name")
})
#Entity
public class Manifest {
...
}
You'd leave your query itself unchanged, but apply the Entity Graph to the query before running it, either as a Load or a Fetch Graph (see link above for explanation):
EntityGraph<EmailMessage> eg = em.getEntityGraph("nameOnly");
entityManager.createNamedQuery("Manifest.getManifestInfo").setHint("javax.persistence.loadgraph", eg).getResultList()

How to use 'Insert' in a nativeSQL query in Hibernate outside the mapped class ?

In Hibernate, you can use the 'SELECT' queries in native SQL like this :
Query query = session.createSQLQuery("SELECT ... FROM ...");
But I would want to use an 'INSERT' query.
So, I looked at the documentation, and it seems you must go directly to the mapped class and write the code inside it.
But I would want to use it as I do for a 'SELECT' query (outside the mapped class) since it looks much more pratical.
Indeed, why would the treatment be different between 'SELECT' and 'INSERT' for a hibernate native SQL query ?
An HQL INSERT cannot be used to directly insert arbitrary entities—it can only be used to insert entities constructed from information obtained from SELECT queries (unlike ordinary SQL, in which an INSERT command can be used to insert arbitrary data into a table, as well as insert values selected from other tables).
Here’s the syntax of the INSERT statement:
INSERT INTO path ( property [, ...]) select
The name of an entity is path. The property names are the names of properties of entities listed in the FROM path of the incorporated SELECT query. The select query is an HQL SELECT query (as described in the next section).
As this HQL statement can only use data provided by an HQL select, its application can be limited. An example of copying users to a purged table before actually purging them might look like this:
Query query=session.createQuery("insert into purged_accounts(id, code, status) "+
"select id, code, status from acount where status=:status");
query.setString("status", "purged");
int rowsCopied=query.executeUpdate();
Or you can use
session.persist(obj);
where obj is the object of the POJO class let say TestClass
TestClass obj=new TestClass('','',''); //paramatrized constructor for the values you want to insert in your database.

How to find using JPQL if member value is in a collection of values

I have an object in which a member is an enum, and I want to write a query returning all elements for which that member is in a list of values. So, I've written the following JQP query
#NamedQuery(name = MyBean.FIND_BY_STATUSES, query = "select t from "+MyBean.TABLE+" t where t.status member of :statuses"),
class MyBean {
#Enumerated(EnumType.STRING)
private MyEnum status;
}
That I try to get using the following EJB code
Query findByStatuses = getEntityManager().createNamedQuery(MyBean.FIND_BY_STATUSES);
findByStatuses.setParameter("statuses", Arrays.asList(statuses));
return findByStatuses.getResultList();
Unfortunatly, Glassfish endlessly tells me I'm wrong (which I am, obviously).
But what do I have to fix ? and how ?
First your query references to table name, so it tries to be kind of SQL, but maybe database does not have "MEMBER OF"-operator which would be suitable for this kind of use, so let's try with JPQL. There we cannot use MEMBER OF, because it takes path expression as an argument, and that is not what we provide in setParameter. Instead we use IN:
#NamedQuery(name = MyBean.FIND_BY_STATUSES, query = "select t from MyBean t where t.status in(:statuses)")
No need to modify part where you run query.

Simple jpa question

I have to go through some code of a project to implement some missiong functionality.
It uses jpa.In some popj classes i have found
#Entity
#Table(name="TYPE")
#NamedQueries( {
#NamedQuery(name = "getTypes", query = "SELECT dct FROM Type dct")
})
I know that i can used to get all records by using this query.Does this query return all records in type table?
This query will return all the Type entities including subtypes, if any. And since I can't say if this there are any subtypes, I can't say if this query will be restricted to the TYPE table.
Yes, it does. It generates an SQL query that looks roughly like this:
SELECT [column list here] FROM type

Categories