How to use clause in order in Hibernate - java

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"));

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!

Conditional SQL where clause in 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

How to select a list of objects as part of the constructor argument for a Hibernate group by query

I'm trying to figure out how to select a list of objects as part of a Hibernate group-by query. I know how to do it a harder way, but I'm curious if there is some special sugar syntax that achieves the same thing.
Basically, I have a query of this structure:
select com.myapp.domain.TagSummary(
tag.id, tag.term, tag.description, tag.synonyms, count(user)
)
from User user
join user.tags tag
I'd like to store the tag.synonyms as a List<Tag>. Is that possible, or do I need to query the cross product and do the separation manually after the query results come back?
Alternatively, what I really want in the end is a list of synonym terms separated by commas. So if a tag is spring and it has synonym terms spring-framework and spring-framework-3.1, it would be great to put into the constructor the string spring-framework, spring-framework-3.1. Is that possible?
EDIT: I have learned that I can use group_concat() to achieve the second half of the functionality, but it's only available in MySQL. Is there a way to make it available in hsqldb as well? In Spring 3.1, how do I add this function to Hibernate? I know I should call something on Configuration, but I don't know what bean to access it by.
for (Object[]> result : query.list()) {
Tag tag = (Tag ) result[3];
User user = (User) result[4];
}
You can get more information from this link
https://derrickpetzold.com/p/in-and-group-by-count-hibernate/

Flatten a collection as part of an HQL query?

I have a requirement to use a reporting-friendly query from HQL. That is, each column is represented by a standard Java type (Long, Integer, String, List) rather than a mapped class. The values will be used by a third party library, so I have very limited control over post-processing.
My example object tree looks like this:
a.x
a.y (a collection of z)
a.y.z[0].v
a.y.z[1].v
a.y.z[2].v
I would like query to retrieve two columns. The first column is the plain "a.x" field, and the second is a String of a comma separated list of all of the a.y.z.v values. If this is not possible, then having the second column return as a Java list of the a.y.z.v values would be satisfactory.
In short, I would like to flatten the a.y.z.v collection to a csv String or to a List object from inside the query.
I have already attempted the following:
Using the "new" keyword in a list subselect. ie, "select a.x, (select new list(a.y.z.v)) from a". If necessary I could have transformed the contents of the list into a csv, but this caused a syntax error.
Using the "new" keyword with a custom object in a subselect. ie, "select a.x, (select new custom.package.ListToCsvObject(a.y.z)) from a". This caused the same error as the first attempt
Using the "elements()" keyword in the select. Unfortunately, this keyword only seems to work inside "in", "exists" clauses (etc), not as the actual returned value.
The only solution we've been able to find was to create a stored procedure in the database and use that, but such a solution is painfully slow through HQL (it turns a sub-second query into a 30 second query) and therefore is not something we want to continue to do.
I am able to make some limited changes to the Hibernate mapping (so I can add #formula, etc) but I would prefer not to have to make major changes to the database schema to support it. (So no, I don't want to create a denormalized "csv_value" column in the database!)
Could anyone suggest some code or, failing that, an alternative approach to solving this problem?
Try something like this should work. Flattening of list to comma separated string is done in the constructor of your VO class. You can also take a look at resultTransformer, you can create a custom resultTransformer and attach it to the query.
class ResultVO {
String x;
String y;
public ResultVO(String x,List<Z> y) {
this.x = x;
this.y = createCSV(y);
}
}
then in HQL
select new ResultVO(a.x,a.y) from a
A warning - this is not a good way to use JPA. If most of your use cases are like this you should seriously reconsider using some other persistence approach (ibastis, spring jdbc template + sql etc).

iBatis using a set for a resultMap as well as a parameterMap

I want to pass a Set of Strings in an iBatis query for the parameter map as well as return a collection of strings for the result set.
Is this possible?
Example queries ...
SELECT * FROM some_table t WHERE t.some_column IN (values);
UPDATE some_table t SET t.some_column = 'some_value' WHERE t.other_column IN (values);
Walter
If you want to pass a List of Strings as one parameter, for example for building a IN(val1,val2...) query, then you should read about dynamic queries, in particular the Iterate element. See also.
For the return, In SqlMapClientTemplate there is the queryForList method.
As for the Set of String as parameter, I do not know if iBatis handles that; we built an object for that, and when I faced that problem it was in a sql in clause, so I made a loop with comma separated values.
Or you can convert the Set to an HashMap and pass that.

Categories

Resources