What advantages does get have over createQuery?
I can see there might be a slight performance improvement in not having to parse the HQL, but is there any other major advantage to using get over createQuery?
First, it's much quicker to type, is much more readable, and expresses the intent clearly: get an entity by its ID. And it's basically impossible to make an error, whereas you could have a typo in your HQL query.
Regarding performance, the main advantage is that it executes a select statement only if the entity is not in the session cache yet. An HQL query will be executed every time. And if you have a second-level cache, get() will avoid executing a query completely if the entity is already in the second-level cache.
get() uses directly session to retrieve objects.
get() only useful when you want to load an object i.e. SQL SELECT.
Like save() and persist() result in an SQL INSERT, delete() in an SQL DELETE and update() or merge() in an SQL UPDATE.
limited control and we need specify an entity that we need to extract.
createQuery() uses HQL
Using HQL we can write all CRUD queries.
give more control we can specify HQL(SQL like) clauses.
HQL is the own query language of hibernate and it is used to perform bulk operations on hibernate programs
An object oriented form of SQL is called HQL.
Here we are going to replace table column names with POJO class variable names and table names with POJO class names in order to get HQL commands
Sometimes it is very hard to write with other alternatives. Using HQL we can implement faster.
Related
I am using entityManager in my DAO.
To create table, i am using:
String CREATE_TABLE = "CREATE TABLE if not exists cats (name varchar(255) PRIMARY KEY NOT NULL, age int NOT NULL);
To delete table i am using:
String DELETE_TABLE = "DROP TABLE examples";
To execute it i am using:
entityManager.createNativeQuery(sql).executeQuery();
How can i do the same using JPQL (i have an #Entity for it if needed)?
Which method should i prefer - createNativeQuery() +SQL OR createQuery() +JPQL?
You cannot create a table as jpql specification says. When it comes to querying, it depends.
Jpql advantages:
Jpql takes advantage of mapping (lazy / eager loading, relatinships) - it uses what you have already defined. In SQL you would have to map the result somehow.
Queries can be stored in cache to provide better performance.
Persistence context doesn't need to be flushed before query.
You can use IDE to change the name of the entity together with queries. They are easier to maintain.
DBMS agnostic - you can change database any time, it'll work (this can also be a disadvantage - the syntax is limited by sql standards).
SQL advantages:
You can use vendor specific dialect, it overcomes the shortcomings of jpql validation.
DML operations are supported, such as cropping or creating table. Also indices and partitioning.
You have greater control of queries to db.
To sum up: unless you need vendor specific queries that would possibly ease implementation and/or improve performance, jpql should be the choice. Schema modeling shouldn't be done at runtime.
I'm getting the "No data type for node" error when I run this query:
session.createQuery("select nextval( 'next_num_seq' )")
which I know means that I need to make it a property of a class, but I haven't been able to find a way to add a sequence to a class, only how to make a sequence generate IDs for a class.
Is there a way to include a sequence in a Hibernate mapping that isn't an ID generator?
As such, this question is valid, yet the path to the solution is headed in the wrong direction. Mapping a Sequence into a managed domain entity is not a "good" idea, as these are two separate concepts.
Sequences, such as the one you are trying to query from a PostgreSQL backend, are a central concept for the generation of unique IDs for primary key values of tuples or - from an ORM application perspective - Java objects. Thus, it is not clever to map their current state to a domain entity. Instead, one sets a single, particular value drawn from such a sequence - e.g. next_num_seq - into one particular object to be persisted in a relational database. Therefore, the related class of such an domain object is linked to this sequence by, for instance, dedicated ORM annotations (or via similar approaches).
In the JavaDoc of the Session interface we find the method createNativeQuery(String sql) which is inherited from the EntityManager interface, see also here.
It is described as follows:
Query createNativeQuery(java.lang.String sqlString)
Create an instance of Query for executing a native SQL statement, e.g., for update or delete.
Parameters:
sqlString - a native SQL query string
Returns:
the new query instance
Thus, you could modify your code to execute the native query against your PostgreSQL database as follows:
Query q = session.createNativeQuery("select nextval( 'next_num_seq' )");
This gives you the option to read the next valid sequence value as a long or Number instance for your programming purposes.
Note well: Be careful not to reuse this value multiple times (for several objects), as this might cause consistency trouble in your backend when used, for instance, in the context of separate threads.
Hope this helps.
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.
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.
How do you join across multiple tables in an efficient way using JPQL
select a.text,b.text,c.text,
from Class1 a, Class2 b, Class3 c
where a.id=b.b_id and b.id=c.b_id and a.text like ... and b.text like ...
I am doing something like this, the tables only have a few thousand rows, yet the query takes 5-6 seconds to run. I assume it is joining all of the tables before doing the filter
I know the speed may be JPA vendor implementation specific, but I suspect this is not the proper way to write this query!
See what SQL query has been generated. Then EXPLAIN that query and try to optimize it. For example, make sure you have proper indices.
If you don't like the SQL which JPA is generating (but I doubt its generating "bad" SQL) you can always use a Native Query.