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

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.

Related

DISTINCT keyword gets removed from the query

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.

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.

SELECT e From Employee e -- why a redundant "e"?

Sample query:
SELECT e FROM Employee e WHERE SUBSTRING(e.name, 3) = 'Mac'
In this syntax, it seems intuitive to say SELECT e, that e is now declared or defined(?). However, isn't the second e: FROM Employee e redundant?
This is a throwback or similarity to SQL SELECT syntax?
The second e is a identification variable. It actually defines e by telling the JPQL parser that you are using e somewhere else in your query, and that it refers to the Employee entity. The first occurrence of e is where you usa that e.
So, it's not redundant. If you leave out the first one, the JPQL parser doesn't know what to select. If you leave it out the second time, you're selecting something that the JPQL parser doesn't know.
JPQL syntax is a little different with normal SQL syntax.According to your sample,first e is represent * of normal SQL. So it is not redundant. But you use JPA 2.x, using criteria query is more better than JPQL
I came to this question with the same concerns as you are. I noticed that when you select * the results comes in columns, and when you select e there's only one column with some kind of serialized entities as results. So I found a pretty good explanation about this at http://www.thejavageek.com/2014/03/17/jpa-select-clause/
SELECT e FROM Employee e
This is quite similar to SQL, the difference is:
This query does not return a set of records from columns, instead it
returns an entity.
This entity is aliased to e , it is called as
identification variable.
This identification variable is tied to
Employee type and it means result will be an entity of Employee
type.
IMO there is no need to use the second e in this case (yes it is redundant) if you have single query like this. It makes sense when you join two tables and if those two tables have common column names then you would select each column using that table alias 'e'
use "e." (which columns you have)
SELECT e.name, e.e FROM Employee e WHERE SUBSTRING(e.name, 3) = 'Mac'
DISCLAIMER: This only works with Hibernate as JPA implementation since this information corresponds to HQL.
In this simple case you don't have to use the e (which is nothing more than an alias). Since you are selecting the complete entity, you even don't have to write the select e part. So you can write:
FROM Employee WHERE SUBSTRING(name, 3) = 'Mac'
Explanation:
In the from part, you specify for which Entities you are looking for. The e behind the Employee is just an alias for Employee which you can use to address the whole object (the select part) or attributes from it. In simple queries you don't need it, but as soon you have a join in your query, it's always a good idea to use an alias.
The select part of the query is for selecting which attributes of an entity you want to get back. If you omit the ´selectpart or just specify the alias (e` in this case), JPA gives back the whole Entity. In SQL this does usually not work (at least for Oracle).
To answer your question in the comment: You can use the alias e in the select part of the query. But in Order to do so, you must teach JPA what this e refers to. And this is what the from Employee e part is doing.

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.

EclipseLink refuses to map native query on PostgreSQL to entity

I have a JPA entity class (one of many) and I can run JPQL queries on it, returning that entity without any problem. However, when I attempt to run any named native query that selects all the fields on the underlying table, instead of mapping to the entity and returning a list of that entity type, I get a java.util.Vector of object arrays containing the result set. That is, the data is being returned, but not mapped to the entity. This is made worse by Java's fake generics, because the error manifests itself as a NumberFormatException in the EL parser.
My query calling code:
return em.createNamedQuery("ClinicDoctor.findUnchangedByClinicSystemId",
ClinicDoctor.class)
.setParameter(1, clinicSystemId)
.getResultList();
When I switch EclipseLink logging to FINE and run a JPQL query, the column names selected exactly match the column names I'm selecting in the native query.
Am I missing something? Is there some flaming hoop I should be jumping through to get the mapping to work?
Wouldn't you know it, right after asking this question I discovered that I just had to set the result-class attribute on the <named-native-query/> tag in my orm.xml and it worked.

Categories