How to get jpql of named query? - java

Let say there is the below definition:
#Entity
#NamedQueries({
#NamedQuery(name = "name1", query = "SELECT n FROM SomeEntity n where n.name= :name"),
#NamedQuery(name = "name2", query = "SELECT n FROM SomeEntity n where n.name <> :name")
})
public class SomeEntity ......
How to programmatically get a definition of the named query ?
For example the bellow code snippet should print a definition of name1 query, I don't know how to get this definition in code:
String queryString = ????????.getSqlOfNamedQuery("name1");
// the below line should print: SELECT n FROM SomeEntity n where n.name= :name
System.out.println( queryString );

You can use the unwrap method and provide it with a vendor specific class. I saw this in an old DZone article. I've tested the EclipseLink version and it works for me:
Query query = entityManager.createQuery("....");
For EclipseLink:
String sqlString = query.unwrap(JpaQuery.class).getDatabaseQuery().getSQLString();
For Hibernate:
String sqlString = query.unwrap(org.hibernate.Query.class).getQueryString();
You could also check your database logs (i.e. /var/log/postgres/postgres.log) but you might have other requirements that necessitate a programmatic approach.

Related

Same #NamedQueries in two different entities gives warning

I've same #NamedQueries in two entities as like below:
#Table(name = "STUDENT_TABLE")
#NamedQueries({
#NamedQuery(name = "getStudentById", query = "SELECT s FROM Student s where s.stdId=:stdId"),
#NamedQuery(name = "getStudentByName", query = "SELECT s FROM Student s where s.fName=:fName and s.lName =:lName")
})
#Table(name = "MARKS_TABLE")
#NamedQueries({
#NamedQuery(name = "getStudentById", query = "SELECT s FROM Student s where s.stdId=:stdId"),
#NamedQuery(name = "getStudentByName", query = "SELECT s FROM Student s where s.fName=:fName and s.lName =:lName")
})
While I'm working on the above, I'm getting a warning like below:
openjpa.MetaData: Warn: Ignoring duplicate query "getStudentById" in "class Student". A query with the same name been already declared in "class Marks".
openjpa.MetaData: Warn: Ignoring duplicate query "getStudentByName" in "class Student". A query with the same name been already declared in "class Marks".
What is the reason and how can we get rid of this warning?
The scope of #NamedQuery is the entire persistence unit.
It does not matter that they are defined on different entities.
Most likely when you define a duplicate name, one of them will be overriden during building of the persistence unit.
Good practice is to prefix your named queries with the entity names:
#NamedQuery(name = "Student.getStudentById"..
#NamedQuery(name = "Marks.getStudentById"...

CRudRepository native query could not return Result Set

I have a simple test query inside a CrudRepository interface that should return a List of entities.
public interface TestRepository extends CrudRepository<Test, TestId> {
#Query(value = "SELECT p FROM test p ", nativeQuery = true)
public List<Test> getTests();
}
When I test this I get the exception:
org.springframework.dao.InvalidDataAccessResourceUsageException: could
not extract ResultSet
If I don't use native query it works, but I want to use native query because I want to extend the select.
In order to make your query work :-
#Query(value = "SELECT * FROM TEST ", nativeQuery = true)
public List<Test> getTests();
The reason is simply because you are writing native query."SELECT p FROM test p" is not a native query
2 problems
in native SQL use native SQL :)
#Query(value = "SELECT p.* FROM test p ", nativeQuery = true)
your native Query returns an Object[] or a List of Object[].
You can change that, if you provide additional mapping information to the EntityManager.
By doing this you can tell the EntityManager to map the result into managed entities, scalar values of specific types or POJOs.
The simplest way to map the result of a native query into a managed entity is to select all properties of the entity and provide its as a parameter to the createNativeQuery method.
(sorry for using other examples)
Query q = em.createNativeQuery("SELECT a.id, a.version, a.firstname, a.lastname FROM Author a", Author.class);
List<Author> authors = q.getResultList();
All other mappings, like the following one which maps the query result into a POJO, need to be defined as SQLResultSetMappings.
#SqlResultSetMapping(
name = "AuthorValueMapping",
classes = #ConstructorResult(
targetClass = AuthorValue.class,
columns = {
#ColumnResult(name = "id", type = Long.class),
#ColumnResult(name = "firstname"),
#ColumnResult(name = "lastname"),
#ColumnResult(name = "numBooks", type = Long.class)}))
To use this mapping, you need to provide the name of the mapping as a parameter to the createNativeQuery method.
Query q = em.createNativeQuery("SELECT a.id, a.firstname, a.lastname, count(b.id) as numBooks FROM Author a JOIN BookAuthor ba on a.id = ba.authorid JOIN Book b ON b.id = ba.bookid GROUP BY a.id", "AuthorValueMapping");
List<AuthorValue> authors = q.getResultList();
#Query(value = "SELECT * FROM test p ", nativeQuery = true)

JPA - Select All Rows from Dynamic Table Name

Hi guys I am new to jpa, named queries, etc.. and I need something like this:
select t from :tableName t
Later in code I want something like this:
em.createQuery(...);
setParameter("tableName", "Person")
Result would be:
select * from person
How to write such a generic jpa query statement allowing to select all rows from :tableName which may be defined at runtime? thanks in advance
Try this I think this works well
EntityManagerFactory emfactory=Persistence.createEntityManagerFactory("Eclipselink_JPA" );
EntityManager entitymanager = emfactory.createEntityManager();
Query query = entitymanager.
createQuery("Select p from Person p");
List<String> list = query.getResultList();
setParameter("foo", foo) is used to set the value for column of the table not to set the table name. I do not think it will work, as you want to set the table name dynamically.
You can try this:
public returnType foo(String tableName){
String jpql = "SELECT t FROM " + tableName+ " t";
Query query = em.createQuery(jpql);
//rest of the code
}

EntityManager query cannot resolve property

I am using JPA to query an OracleSQL database.
However, I am getting the error:
Request processing failed; nested exception is java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: CLIENT_ID of: com.fdmgroup.pojo.File [SELECT c FROM com.fdmgroup.pojo.File c WHERE c.CLIENT_ID = :clientId]
When I write the following query
String sqlQuery = "SELECT c FROM XD_FILES c WHERE c.CLIENT_ID = :clientId";
TypedQuery<File> query = em.createQuery(sqlQuery, File.class);
query = query.setParameter("clientId", clientId);
ArrayList<File> clientFiles = (ArrayList<File>) query.getResultList();
File has this column
#ManyToOne(targetEntity = Client.class)
#JoinColumn(name = "CLIENT_ID")
private Client client;
I am unsure why as it appears to have the field "client" linked to "CLIEND_ID".
You will need to mention the property name in the query and not the column name.
So the query should look like the following:
String sqlQuery = "SELECT c FROM XD_FILES c WHERE c.clientId = :clientId";
Your query seems native query and not a JPQL, you can solve this in two ways.
1) change em.createQuery(sqlQuery, File.class); to em.createNativeQuery(sqlQuery, File.class);
2) Change your query from native query to JPQL, your query should be like
select c from File c where c.client.clientID=:clientId
(Assuming clientID is primary key column name in Client class)

Why EclipseLink Query cache only works when I use query.getSingleResult()?

My entity has a named query which looks like this:
#NamedQuery(name = "Person.find", query = "select p from Organization p where p.name=:NAME")
In my code I want to set the query cache hint:
query.setHint("eclipselink.cache-usage", "CheckCacheThenDatabase");
If I try to get whole result list:
List<Person> result = query.getResultList();
EclipseLink throws an exception:
Exception [EclipseLink-6124] (Eclipse Persistence Services - 1.0.1 (Build 20080905)): org.eclipse.persistence.exceptions.QueryException
Exception Description: Required query of class org.eclipse.persistence.queries.ReadAllQuery, found class org.eclipse.persistence.queries.ReadObjectQuery
If I try to get only a single result, it works:
Person person = query.getSingleResult();
If I remove the query hint, then getResultList() works also.
I don't understand the exception - isn't it saying that it is specifically expecting getResultList()?? What am I doing wrong?
EclipseLink documentation says:
"EclipseLink does not support the cache usage for native queries or queries that have complex result sets such as returning data or multiple objects."
Also the documentation says:
"CheckCacheThenDatabase – You can configure any read-object query to check the cache completely before you resort to accessing the database."
So the behaviour seems to be ok, I just found the exception misleading.
EDIT: Try something like this in the entity definition, that should be enough: (Coded on the web page so there can be errors)
Entity
#Cache(expiry = 3600000, // 1 hour size = 10000)
#NamedQueries({
#NamedQuery(name = "Person.findByPK", query = "select p from Person p " +
"where p.name=:NAME",
hints = {
#QueryHint(name = QueryHints.CACHE_USAGE,
value = CacheUsage.CheckCacheThenDatabase),
#QueryHint(name = QueryHints.QUERY_TYPE, value = QueryType.ReadObject)
}
})

Categories