I have inherited a groovy code base (that among other things) uses Hibernate as an ORM as part of Dropwizard and I've in the process of updating the dependencies I start seeing the following warnings.
org.hibernate.orm.deprecation: HHH90000022: Hibernate's legacy org.hibernate.Criteria API is deprecated; use the JPA javax.persistence.criteria.CriteriaQuery instead
As an experiment I tried updating one of the queries to use the new CriteriaQuery API. However pretty quickly I ran into an issue, the old code uses setMaxResults(). I assume under the hood this is using the LIMIT to limit the number of results.
How to I limit the results of a CriteriaQuery to 1?
A related question, how do I do pagination with CriteriaQuery?
I tried reading through the Hibernate 5.3 users guide, (especially chapter 16 the the new API) searing for "limits" and "max results" and such and all the talk I could find was in the "Legacy Hibernate Criteria Queries".
I'd be happy to provide some example code if it helps, but you could just use the example from the manual (Example 534. Selecting an attribute) and show how to enhance it by limiting the results.
Define setFirstResult() and setMaxResults() on the Query like this (offset=0 and limit=10):
sessionFactory.getCurrentSession().createQuery(criteriaQuery).setFirstResult(0).setMaxResults(10).getResultList());
To paginate you just have to set the first and max (assuming you're passing in a Pageable Object:
criteria.setFirstResult(pageable.gotOffset());
criteria.setMaxResults(pageable.getPageSize());
Also, to limit, just call:
Criteria queryCriteria = session.createCriteria(MonthlySubscriber.class);
queryCriteria.setFirstResult(0);
queryCriteria.setMaxResults(1);
monthlySubscriberList = queryCriteria .list();
While ORM frameworks like hibernate does simplify the activities of accessing and modifying data in RDBMS. And it's features like lazy loading, caching etc also help in better application performance when used properly.
But what I am thinking of is if the query generator or optimizer is not using the best query - say not following the proper ordering of tables during a join and not using the most suitable join strategy etc.
How can i optimize the query or say hibernate to generate a better query which is more optimal than the one it is generating by default.
(probably if I am not wrong, this question applies to other ORM frameworks like iBATIS etc also)
EDIT following answer from S. Bhattacharjee - I would also hope that Hibernate will generate the best optimal query. But on the other side even when using Oracle SQL executor in Oracle GUI, it's some time the case that the Optimizer DOES NOT use optimal plan. But I can influence it by writing the query more specifically. (don't ask me how it's done, if some one knows please indicate. I am no SQL expert. I need to analyse this case to ensure the systems flexibility and optimization's are not limited because of frameworks). So
CASE 1 - consider hibernate is not generating optimal query. So how to influence it to generate optimal query.
CASE 2 - hibernate is generating optimal query. But SQL engine is using a plan that is not optimal. Query and Plan (or execution) are different from my understanding. I am not sure if this is a valid case or not. So ignore if not applicable. But if anyone think this is a valid case even if they can't answer, plz leave a comment to bolster this point.
Next speaking about Hibernate query generator - another question pops in to my mind. Does Hibernate know about the Logical Structure of DB (I don't expect it to know the physical design anyway and may not be relevant to consider it here).
a) If it does know logical db design, how does it know about it.
b) if it does not know logical db design, then how can it be sure about the query being optimal.
Well, in my opinion hibernate generates a good and optimal query. Please be more clear on what grounds you are saying so, may be with an example? However if you want you may write your own SQL queries. Below is a very small example
Query query = session.createSQLQuery("select c.codename from
codes c where c.code = :paramcode")
.setParameter("paramcode", "900");
List result = query.list();
Hell, I can't find a way to use the postgres 'WITH' clause with JOOQ.
Could you please let me know if it's supported by JOOQ?
Thanks
Common table expressions (the "WITH clause") are currently not supported in jOOQ. There is a pending feature request on the jOOQ road map for CTE's: #454. As of jOOQ 3.0, there are currently no plans of actually supporting it, though.
(Your best option to push things a little bit is to discuss this topic on the jOOQ user group)
I have an issue.
I have SQL that I need to append different type of "restrictions" or even do a join. This depends on user's search criteria.
This SQL will involve different table as it can search one-to-many relationship, therefore hibernate ORM can't support my requirement.
May I know if there is a design pattern to help construct such SQL statements?
The design pattern that fits to the problem of representing a language statement is the Interpreter pattern. But before you start to code your SQL parser, take a look to ANTLR.
And what is more important, ask yourself two questions:
Are the number of different SQL's justify the effort of develop a general SQL interpreter solutions instead of programming (just if-else statements) my 5-10 different queries?
Have I reviewed in detail the Hibernate reference manual?
I exactly have a similar requirement where I have a context-free language to define the search criteria, parsed to ParseEntry objects in a ParseTree which are analogous to the Restrictions. I use a SQLQueryGeneratorVisitor to visit the parse table and generate the SQL query, similary a HibernateCriteriaGeneratorVisitor if the criteria needs to be generated for a single entity. So, I essentially used the Visitor pattern making the parse tree and the entries visitable so that different types of criteria can be generated (SQL/Hibernate or something else in future).
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I've stumbled over a nice SQL builder framework, called JOOQ. BTW, in Russian JOOQ sounds like noun meaning "bug" (as an insect), "beetle" ;)
If you have any feedback about JOOQ, it's performance and such, please share. Links to blogs about JOOQ also welcome.
I think I should answer here also because I started using jooq one and a half months ago so I have some experience with it.
I wanted to use tool like jooq because:
ORM is an overkill in my current project (distributed calculations platform for cluster) since I need to read and write only separate fields from db, not complete table rows and some of my queries are complex enough not to be executed by simple and lightweight ORMs.
I wanted syntax autocomplete for my queries so that I don't need to keep my whole DB in mind
I wanted to be able to write queries directly in Java so that compiler could check basic query syntax on build.
I wanted my queries to be type-safe so that I couldn't accidentally pass a variable of one type, where another one is expected.
I wanted SQL, but I wanted it very convenient and easy to use
Well, with jooq I was able to achieve all that. My main requirement was for jooq to handle complex enough queries (nested, with grouping etc.). That was fulfilled.
I also wanted to be able to run queries using as few lines of code as possible and was able to reach this with jooq fluent API which allows jquery-like calls to perform SELECTs.
On my way using of jooq I reported a one or two bugs and I must say, that they were fixed surprisingly fast.
I also missed some features and again I must say, that I already have almost all of them.
What I liked very much, is that jooq now uses SLF4J for reporting some very interesting data about it's performance as well as for outputting the actual queries it has built. It really helped me with debugging.
Jooq even generate Java artifacts for stored procedures, UDFs and updatable recordsets, which I don't use currently, though.
What's important, jooq transparently supports DB2, Derby, H2, HSQLDB, MySQL, Oracle, PostGreSQL, SQLite, SQL Server, Sybase SQL Anywhere. Pretty extensive list, I think.
Jooq has support forum in Google groups where Lukas is day and night ready to answer even the stupidest of my questions.
Jooq supports Maven and that's a great relief for me since all my Java projects are Maven-based. We still miss Maven plugin for generator, but that's not important since running generator is a piece of cake.
Writting my queries with jooq I suddenly discovered, that they became really portable because I almost never used any MySQL-specific feature in the code since jooq tries to be as portable as possible. For those who can't live with such peculiarities, as I know support for SQL extensions is under the way also.
What does jooq lack for a moment from my point of view?
Well, there is no fluent API for statements other than SELECT. This complicates code a little and makes UPDATE/DELETE statements a little more complicated to write. But I think this will be added soon. Just implemented in 1.5.9! Ha! Too quick for me ;)
And one more thing. Jooq has a good manual, but... I don't know. May be I just don't understand it's structure or architecture... When I started using jooq for the first time, I opened one page after another looking for a feature I need. For example, try to guess, where in jooq manual UPDATE and DELETE statements are described, looking at contents... But that's really subjective, I believe. I also cannot even explain, what's wrong with manual from my point of view. When I can, I will post a ticket or two ;)
Manual also is not really well-navigable since Trac has no automatic "here, there and back"-like links.
Well, for me in Moscow (Russia) Trac pages doesn't open fast also so reading manual is a little boring.
Manual also misses a good architecture description of jooq for contributors. Jooq follows design-by-contract principle it seems and when I wanted to learn how certain feature is implemented inside by using my usual Ctrl-Click on some method name in IDE, I ended up inside a dull interface with no implementation ;) Not that I'm too smart to start improving jooq right away, but certainly I would enjoy understanding how exactly jooq is architectured from ground to up.
It's a pity also that we cannot contribute to jooq manual. I expected it to be in some kind of wiki.
What I would also want to improve, is the way news are reported. I would prefer link to manual there or examples how this or that new feature works.
Release notes link in manual is really just a roadmap. I think, I will do that one myself tomorrow...
Jooq also have relatively small community currently, but I am glad to report that it doesn't affect code quality or the way new features are introduced.
Jooq is really a good project. I will stick to it for my future projects as well. I really like it.
You can also take a look on MentaBean, a lightweight ORM and SQL Builder that lets you be as close as possible to SQL offering a lot of help with the boilerplate code. Here is an example:
Programmatic Configuration:
private BeanConfig getUserBeanConfig() {
// programmatic configuration for the bean... (no annotation or XML)
BeanConfig config = new BeanConfig(User.class, "Users");
config.pk("id", DBTypes.AUTOINCREMENT);
config.field("username", DBTypes.STRING);
config.field("birthdate", "bd", DBTypes.DATE); // note that the database column name is different
config.field("status", new EnumValueType(User.Status.class));
config.field("deleted", DBTypes.BOOLEANINT);
config.field("insertTime", "insert_time", DBTypes.TIMESTAMP).defaultToNow("insertTime");
return config;
}
// create table Users(id integer primary key auto_increment,
// username varchar(25), bd datetime, status varchar(20),
// deleted tinyint, insert_time timestamp)
A simple SQL join query:
Post p = new Post(1);
StringBuilder query = new StringBuilder(256);
query.append("select ");
query.append(session.buildSelect(Post.class, "p"));
query.append(", ");
query.append(session.buildSelect(User.class, "u"));
query.append(" from Posts p join Users u on p.user_id = u.id");
query.append(" where p.id = ?");
stmt = conn.prepareStatement(query.toString());
stmt.setInt(1, p.getId());
rset = stmt.executeQuery();
if (rset.next()) {
session.populateBean(rset, p, "p");
u = new User();
session.populateBean(rset, u, "u");
p.setUser(u);
}
If you are looking for only a SQL builder solution. I have one project which is an ORM framework for Java but it is still premature and in continuous development however handles many primitive usages of databases. https://github.com/ahmetalpbalkan/orman
There is no documentation in this stage however it can build safe queries using only Java chain methods and can handle many SQL operations. It can also map classes-fields to tables-columns respectively.
Here's a sample query building operation for query
SELECT COUNT(*) FROM sailors WHERE
rating>4 AND rating<9 GROUP BY rating HAVING AVG(age)>20;
Java code:
QueryBuilder qb = QueryBuilder.getBuilder(QueryType.SELECT);
System.out.println(qb
.from("sailors")
.where(
C.and(
C.gt("rating", 5),
C.lt("rating", 9)))
.groupBy("rating")
.having(
C.gt(
new OperationalField(QueryFieldOperation.AVG,
"age").toString(), 20)
).getQuery());
(LOL just give up developing that framework!)
Most probably that won't work for you but just wanted to announce my project :P