DISTINCT keyword gets removed from the query - java

Does any one have a clue why DISTINCT keyword is removed from the query when using DataNucleus (that's the software the company I work for uses)? I was able to debug the code and verified that the keyword is actually with the query. But by the time this function is called within JPAEntityManager
createQuery(CriteriaQuery<T> criteriaQuery)
the DISTINCT keyword is removed. Debugging showed me it has something to do with
criteria.getCompilation(ec.getMetaDataManager(), ec.getClassLoaderResolver());
function call. Somehow createQuery() function works fine with SELECT COUNT(DISTINCT DN_THIS) but not with SELECT DISTINCT FROM.
I hope some of you have at least a slight idea where the problem is since I'm fairly new with JPA and SQL queries in general that I can't find a quick solution on my own.
The query I'm trying to perform is as follows:
SELECT DISTINCT DN_THIS FROM Hop DN_THIS JOIN DN_THIS.tags t WHERE ((DN_THIS.entityStatus <> 'DELETED') AND ((t.name = :DN_PARAM_4) OR (t.name = :DN_PARAM_5))) ORDER BY DN_THIS.name ASC
Thank you!

I prompted a developer of DataNucleus, who seems to have already fixed the use of DISTINCT in criteria which was simply not being passed across to the generated query.

Related

JPA query from java Object

How can i use jpa for query over an object (not an entity)?
For example this simple code:
String [] theList = {a,b,c,d}.
Query q = new Query("Select tl from theList tl")
Reason behind: the queries are dynamically created and executed, but the objects in the from clause of the jpql query aren't necessarily mapped tables. In some cases there are just an Object, So the actual behavior needed is modify the query during execution of the program to meet the criteria, but i don't know how to modify the query.
Edit: I Don't use native queries because of portability of code. It will be the last option.
What you're looking for is called LINQ, and unfortunately (?) it is available only in C#.
However, you can partially emulate it with Stream(s).
A Stream offers basically all the operators you need
.filter() where
.max() max
.sorted() orderby
.limit() limit
.skip() offset
.collect(groupingBy()) group by
And so on. Just give a look at the Javadoc!
I think 'JdbcTemplate' would suffice your requirement.
JdbcTemplate gives you the flexibility to run native queries and map them to a Java class.
However, you'll have to explicitly map your Java class with the column names in the database.
I have solved using joSQL. Is a powerfull opensource tool that allows you to query over java objects using "sql". It is not jpa but satisfied my needs.
Another tool i have seen that do that is called querydsl.

When use createQuery() and find() methods of EntityManager?

I would like to know the difference between on these methods.
When use the createQuery()and find() methods of EntityManager ?
What the advantages about each of them ?
Thank you for answer me.
You use find when you want to look up an entity by primary key. That means you know exactly what you're looking for, you just want to pull it out of the database.
You use createQuery when you want to find entities using criteria or if you want to use a JPQL statement to define what you get back. So you would use the query when you want to get an entity or collection of entities matching some conditions.
The createQuery method allows you to create a JPQL statement that will be executed. The JPQL statement allowed is much more dynamic than the one executed by find. For example given the following table:
create table CAT(
cat_id integer,
cat_name varchar(40)
)
You could execute a query to find the cat by name.
entityManager.createQuery("select c from Cat c where c.name = :name");
The find method only allows you to retreive an object using its primary key. So to use the find method for the above table:
entityManager.find(Cat.class, new Integer(1));
In a nutshell, createQuery allows you to retrieve entities in a more dynamic fashion, while find limits you to searching for an entity with a known id.

How does setParameterList in hibernate work?

I am having some problem with the setParameterList api of hibernate.
I am trying to pass in a Collection to a SQLQuery and doing an "in" clause search.The records exists in the DB and doing a raw query, I am able to retrieve them or if I just replace them in the same Hibernate SQL like emp.emp_name in ('Joe','John'), I am able to get the desired result set. I am confused as to why would Hibernate fail to replace the Collection in place of the named parameter. Here is the code :
session.createSQLQuery("select emp_id as id from emp where emp.emp_name in (:empNames)")
.addScalar("id",Hibernate.INTEGER)
.setParameterList("empNames",new String[]{"Joe","John"})
.list()
I have looked at the Hibernate Documentation for setParameterList but I am not able to reason out this particular behavior.
I suspect the problem is precisely because you're using createSQLQuery. The single parameter here needs to be changed into multiple parameters in the real SQL, but by using a "raw" query you're telling Hibernate not to mess with the SQL.
Can you use a "normal" Hibernate query instead?
Just remove the parenthesis around the parameter name :
session.createSQLQuery("select emp_id as id from emp where emp.emp_name in :empNames ")
.addScalar("id",Hibernate.INTEGER)
.setParameterList("empNames",new String[]{"Joe","John"})
.list()
I would not suggest to use (N)Hibernate's parameter lists. Query plans in cache are not used when the number of elements in parameter list is different. So it means your query is often hard parsed and compiled. Queries are slower, database load is higher and plan cache is full of plans generated for the same query.

A set of questions on Hibernate quering

Please help me with these Hibernate querying issues.
Consider the following structure:
#Entity
class Manager {
#OneToMany
List<Project> projects;
}
0) there are 2 possible ways of dynamic fetching in HQL:
select m from Manager m join m.projects
from Manager m join fetch m.projects
In my setup second one always returns a result of cartesian product with wrong number of objects in a list, while the first one always returns correct number of entities in a list. But the sql queries look the same. Does this mean that "select" clause removes redundant objects from the list in-memory? In this case its strange to see an advice in a book to use select distinct ... to get rid of redundant entities, while "select" does the job. If this is a wrong assumption than why these 2 queries return different results?
If I utilize dynamic fetching by one of the 2 methods above I see a classic n+1 select problem output in my hibernate SQL log. Indeed, FetchMode annotations (subselect or join) do not have power while fetching dynamically. Do I really can't solve the n+1 problem in this particular case?
Looks like Hibernate Criteria API does not support generics. Am I right? Looks like I have to use JPA Criteria API instead?
Is it possible to write HQL query with an entity name parameter inside? For example "from :myEntityParam p where p.id=1" and call setParameter("myEntityParam", MyClass.class) after this. Actually what I want is generic HQL query to replace multiple non-generic dao's by one generic one.
0) I always use a select clause, because it allows telling what you want to select, and is mandatory in JPQL anyway. If you want to select the managers with their projects, use
select distinct m from Manager m left join fetch m.projects
If you don't use the distinct keyword, the list will contain n instances of each manager (n being the number of projects of the manager): Hibernate returns as many elements as there are rows in the result set.
1) If you want to avoid the n + 1 problem, fetch the other association in the same query:
select distinct m from Manager m
left join fetch m.projects
left join fetch m.boss
You may also configure batch fetching to load 10 bosses (for example) at a time when the first boss is accessed. Search for "batch fetching" in the reference doc.
2) The whole Hibernate API is not generified. It's been made on JDK 1.4, before generics. That doesn't mean it isn't useful.
3) No. HQL query parameters are, in the end, prepared statement parameters. You must use String concatenation to do this.

Select nvl(max(c.EmployeeId),0) in JPQL?

I'm using oracle10g database and eclipselink, I need to obtain the last inserted key from the table so i've created this query
javax.persistence.Query q =
em.createQuery("SELECT nvl(MAX(c.myAtt),0) " +
"from myTable as c");
return Integer.parseInt(q.getSingleResult().toString()); `
But when the table is empy(sometimes it might get empty)
i'm getting ILEGAL ARGUMENT EXCEPTION, cause: JPQL Exception, detail: "An exception occurred while creating a query in EntityManager". What i'm doing wrong?
In the meanwhile somebody else could have inserted something in Autorizaciones and then you receive the wrong id
NVL() is supported now in newer versions of jpql
You could use the COALESCE function. It can be used to achieve the same as nvl. For instance:
select nvl(columna,'1') from table
select COALESCE(columna,'1') from table
Paraphrasing Apu, "I don't know what part of that question to correct first" :-)
First of all, retrieving last inserted key in this way is a VERY BAD THING © It's dangerous, inefficient and most of all, unnecessary as your JPA already does it for you: once you insert your entity, its identifier property will automatically be updated to contain its primary key.
Secondly, as far as your query goes, "myTable" is not something you would use in JPQL, you need to specify your entity name instead (e.g. if you're mapping "Car" to "CAR_TABLE" you should use "Car" instead of "CAR_TABLE" in JPQL queries).
Finally, NVL() is not supported by JPQL. It is supported (sort of, via Expression.ifNull()) by EclipseLink Expressions. Not that you'd need it in a scenario like this, anyway.

Categories