Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use native SQL as a fragment (where clause) of a bigger query made with Criteria API in Hibernate?

I have a following problem. In application, which I am developing, we use Hibernate and every query is written with Criteria API. Now, in some places, we want to add possibility for user to write some SQL code which will be used as part of where clause in a query. So basically, user can filter data displayed to him from database in his own way.

For a few days now, I am trying to find a way to modify our previous queries to acquire result described above. Here is what I know:

  1. It looks like you cannot combine Criteria API with native SQL. You can either write whole query in SQL or use only criteria API. Is that right? I am asking this question because it would be the easiest solution, just to use this SQL code as another predicate in where clause in our query. But I don't think it's possbile on this level.

  2. I know on which table user wants to filter data. So I could just execute native SQL query and use result list as a parameter to IN clause in criteria query. But I don't know if it is efficient with many records in a result list.

  3. So if I cannot do it on criteria API level, I thought that maybe I could somehow influence the SQL generetion process and put my SQL in a proper place but it seems to be impossible.

  4. So my real question is: is it somehow possible to have access to SQL code of the query, after SQL generation phase but before actual execution of query? Just to manipulate with it manually? Can it be done safely and as far as possible simply?

  5. Or maybe just try to parse this SQL written by user and use it in criteria query?

Changing existing criteria queries into native SQL queries is rather out of discussion.

like image 491
MichalD Avatar asked Apr 13 '15 11:04

MichalD


People also ask

Can we use SQL statements directly with Hibernate using native SQL?

You can use native SQL to express database queries if you want to utilize database-specific features such as query hints or the CONNECT keyword in Oracle. Hibernate 3. x allows you to specify handwritten SQL, including stored procedures, for all create, update, delete, and load operations.

How can we get data from Criteria in Hibernate?

The Hibernate Session interface provides createCriteria() method, which can be used to create a Criteria object that returns instances of the persistence object's class when your application executes a criteria query.

Can you explain criteria in Hibernate?

In Hibernate, the Criteria API helps us build criteria query objects dynamically. Criteria is a another technique of data retrieval apart from HQL and native SQL queries. The primary advantage of the Criteria API is that it is intuitively designed to manipulate data without using any hard-coded SQL statements.

What is the difference between query and criteria in Hibernate?

HQL is suitable for executing Static Queries, where as Criteria is suitable for executing Dynamic Queries. HQL is to perform both select and non-select operations on the data, Criteria is only for selecting the data, we cannot perform non-select operations using criteria.


1 Answers

Yes, you can get the SQL from the Hibernate criteria using the org.hibernate.loader.criteria.CriteriaQueryTranslator class.

This will allow you to append the additional SQL clause(s) to the end and execute it as a native SQL:

CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, criteria, "myEntityName", CriteriaQueryTranslator.ROOT_SQL_ALIAS);
String select = translator.getSelect();    
String whereClause = translator.getWhereCondition();

Personally though, if faced with this requirement I would shy away from accepting SQL from the end-user and give them a user interface to populate some type of filter object. This can then be converted into HQL criterion, which is much safer and doesn't tie your code as tightly to the database implementation.

Edit based on comments

Example of extracting SQL from a JPA query implemented with Hibernate:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> q = builder.createQuery(MyEntity.class);
Root<MyEntity> entity = q.from(MyEntity.class);
q.select(entity).orderBy(builder.desc(entity.get("lastModified")));
TypedQuery<MyEntity> query = entityManager.createQuery(q);

String sql = query.unwrap(org.hibernate.Query.class).getQueryString();
like image 113
StuPointerException Avatar answered Oct 13 '22 11:10

StuPointerException