How does setParameterList in hibernate work? - java

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.

Related

Convert List<Tuple> to List<Bean>

I don't want to show all my attributes on a table, so I'd like to select only a few columns and then map their values to a bean, something similar to Hibernate's Transformers.aliasToBean(T.class), but using JPA and Criteria.
I'm able to get a List<Tuple>, how could I transform it into a List<T>?
As the the title says, is it possible?
Within JPQL/Criteria queries you can provide arguments to an objects constructor within the query so that the query returns those objects for you. For example:
"SELECT new package.BeanClass(e.attribute1, e.attribute2) from Entity e"
With native SQL queries, if you are using JPA 2.1, you can use ConstructorResult to build the same instances:
http://en.wikibooks.org/wiki/Java_Persistence/Querying#ConstructorResult_.28JPA_2.1.29
But if you are not able to use Jpa 2.1, you will need a provider specific solution such as http://onpersistence.blogspot.com/2010/07/eclipselink-jpa-native-constructor.html

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.

Programmatic, "non-dynamic" construction of HQL queries within the bounds of the JPA

Example:
List<Object[]> list = em.createQuery(
"SELECT 'Foo', 123 FROM IrcEvent ev", Object[].class).getResultList();
What I don't like in that example:
How do I know the table name? Can't I specify the entity class instead?
How do I know the column name? jOOQ provides auto-completion by creating a DSL from the database schema.
There could be syntax errors everywhere.
What I basically want is something like
entityManager.deleteAll(EntityClass.class);
to delete the rows of an antire table (for example).
JPA 2 Criteria API http://docs.oracle.com/javaee/6/tutorial/doc/gjitv.html is for creating type safe queries programmatically, but it does not support deletes

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.

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