Conditional SQL where clause in Java - java

We are looking to to conditionally add where clauses to a SQL where class
For example we have a DAO that has a method with say 10 params.
For each of those params we check if it is null, if not we add an AND to the where clause.
The "base" query is a hard coded string and we concat it with the ANDS.
I'm looking for ideas for a more elegent way of doing this.
We are using hibernate elsewhere in the app

You can use the Hibernate criteria API to dynamically build queries.

For simplicity you can use variable argument method and start a loop for array and check for not null and concat it. otherwise you can use the Hibernate criteria API.

The Hibernate Criteria might be what you want.
http://www.mkyong.com/hibernate/hibernate-criteria-examples/
http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/api/org/hibernate/Criteria.html

Related

Why does Hibernate throw a QuerySyntaxException for this HQL?

While building a query using Hibernate, I noticed something rather odd. If I use sequential named parameters for the ORDER BY clause, Hibernate throws a QuerySyntaxException (the colon prefix being an unexpected token):
createQuery("FROM MyEntity ORDER BY :orderProperty :orderDirection");
However, when this is done with a plain SQL query the query is created without a problem:
createSQLQuery("SELECT * FROM my_entity_table ORDER BY :orderProperty :orderDirection");
I know Hibernate is doing more String evaluation for the HQL query, which is probably why the SQL query is created without an error. I am just wondering why Hibernate would care that there are two sequential named parameters.
This isn't a huge issue since it is simple to work around (can just append the asc or desc String value to the HQL instead of using a named paramater for it), but it struck my curiosity why Hibernate is preventing it (perhaps simply because 99% of the time sequential named parameters like this result in invalid SQL/HQL).
I've been testing this in my local, and I can't get your desired outcome to work with HQL.
Here is quote from the post I linked:
You can't bind a column name as a parameter. Only a column value. This name has to be known when the execution plan is computed, before binding parameter values and executing the query. If you really want to have such a dynamic query, use the Criteria API, or some other way of dynamically creating a query.
Criteria API looks to be the more useful tool for your purposes.
Here is an example:
Criteria criteria = session.createCriteria(MyEntity.class);
if (orderDirection.equals("desc")) {
criteria.addOrder(Order.desc(orderProperty));
}
else {
criteria.addOrder(Order.asc(orderProperty));
}
According to the answer accepted in this question, you can only define parameters in WHERE and HAVING clauses.
The same answer also gives you some ways to have a workaround for your problem, however I will add one more way to do this:
Use the CASE - WHEN clause in your ORDER BY, this would work by the following way:
SELECT u FROM User u
ORDER BY
CASE WHEN '**someinputhere**' = :orderProperty
AND '**someotherinput**' = :orderDirection
THEN yourColumn asc
ELSE yourColumn desc END
Please, note that in this approach would required you to write all the possible inputs for ordering. Not really beautiful but really useful, especially because you would not need to write multiple queries with different orderings, plus with this approach you can use NamedQueries, which would be possible by writing the query dinamically using string concats.
Hope this can solve your problem, good luck!

JOOQ Ordering using CASE expressions

I'm using JOOQ for half a year now and must say that it's quite superb :)
The problem I encountered is: I'm trying to generate plain SQL query containing order by clause with case ... when statements to achieve custom sorting order as described in this part of JOOQ tutorial.
However, when I'm using Field.sortAsc(Collection< T> sortList) method and passing Collection of Strings I get following order by clause in query:
order by
case `type`
when ? then ?
when ? then ?
when ? then ?
when ? then ?
when ? then ? end asc
Because I'm not using JOOQ for executing queries, I need to specify these values myself which is quite inconvenient.
Partial solution to this problem was to pass Collection of Param<String> values obtained from original values using DSL.inline(T) method. However, in that case placeholders still exist and order by clause in query looks like:
order by
case `type`
when 'type_a' then ?
when 'type_b' then ?
when 'type_c' then ?
when 'type_d' then ?
when null then ? end asc
Is this expected behaviour or this can be considered as bug and should be reported?
For now, I worked this problem around by using Field.sort(Map sortMap) method, passing Map<Param<String>, Param<Integer>> to it with incremented integer values. There is minor problem with this method as well, because it returns SortField instance which doesn't have methods like asc(), desc() or sort(SortOrder) so in order to sort with different orders this map should be regenerated.
Thanks in advance for any help!
In order to extract all bind values from a query, use Query.getBindValues(). The sort indirection values should be in there. See also the relevant section of the manual.
Note, it might be generally useful to generate "inline" sort indirection values instead of bind values to prevent this in the future. Execution-plan-wise, I don't think there will be any difference. I have registered Issue #3147 for this.

Hibernate Criteria how to add new construction in Projections or other?

With HQL I can enter the following statement can be made :
SELECT new MyClass(u.name,u.email) FROM User u ;
where MyClass is a normal Javabean with name and email as a Constructor.
I like to use Hibernate Criteria to construct such queries. Is this possible. I know I can restrict the columns to name and email using Projections but how do I get to use the new operator in Criteria ?
You should use
.setResultTransformer(Transformers.aliasToBean(MyClass.class));
This is very good example Hibernate Criteria Transformers.aliasToBean
Every time I look at Criteria API code I remember why I avoid using it:
Anyway see 9.1.4 here:
http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/querycriteria.html#querycriteria-typedquery-multiselect

How to use clause in order in Hibernate

I would like to get objects via Hibernate from database with concrete order. This order is something like that:
as the first I would like to get objects with column titled for example first_column not null,
as the second I would like to get objects with column second_column not null,
as the last I would like to get objects which third_column is the id for another object/table, and this another object has a field with concrete value for example: "something".
I have created criteria in this way:
criteria.addOrder(Order.asc("firstColumn"));
criteria.addOrder(Order.asc("secondColumn"));
but how can I meet the last requirement?
With the restriction I can do something like that:
criteria.createAlias("thirdColumn", "t");
criteria.add(Restrictions.eq("t.field", "something"));
But I have to use order, not restriction with three separate Criteria results, because I am using also setFirstResult() and setMaxResults() of the Criteria to implement pagination in my frontend.
If you can write the statement in SQL then you can probably get away with the approach mentioned in this post which is to create a custom subclass of Order.
I think you can simply use the "." separator and write your code as follow
criteria.createAlias("thirdColumn", "t");
criteria.addOrder(Order.asc("t.field"));

tricky hibernate criteria

I have a sql statement which I want to move it into hibernate criteria, but I am not clue how to do this.
The problem is one of the WHERE clause which looks like the following
...(skip other parts)... ? ILIKE strprefix||'%' ...(continue)
strprefix is the column name, the ? is the place i need to fill in the value.
With criteria, I can use
criteria.add(Expression.ilike(propertyName, value));
but in this case, how can i do this.
Thanks in advance!
You can likely handle this with Restrictions.sqlRestriction(String sql).
You can't do this in Criteria, columns are set since they represent the properties in your domain object. You need to query against the property not the other way around.

Categories

Resources