Do you like the Criteria api of JPA 2.0? Do you use it with framework? [closed]
Asked Answered
T

4

18

I'm used to work with Criteria API in Hibernate, and just watched how the Criteria in JPA 2.0 work.

What i like most in the Criteria of Hibernate is the ease we have to compose with Criterions.

The JPA Criteria seems quite heavy for me, and not as fluent as the Hibernate Criteria. One of the major benefits compared to Hibernate for me seems to be the use of the metamodel (Entity_.java classes), but still it's a bit heavy too since you have to maintain 2 classes, or add an annotation processor (though its quite easy to integrate with maven plugins)

I've read a blog on SpringSource that permits to reduce the complexity of composing with "JPA Predicates" and do a bit like with Criterions in Hibernate.

The Querydsl project seems interesting.

http://blog.springsource.com/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

Just wonder, for those using JPA2, are you using Criteria API or it's a bit too heavy for you?

For those familiar with Hibernate Criteria and who now work with JPA Criteria, dowhich approach do you like the most and why?

Are you considering of using, or using, a framework like Querydsl or Spring Specifications over JPA2 for building your query predicates? Do you think these frameworks are mature enough to be adopted?

Tympan answered 6/5, 2011 at 8:42 Comment(4)
You don't have to use the metamodel classes with Criteria obviously, instead just using strings (like in "Hibernate Criteria").Maxinemaxiskirt
i didn't know we could use strings, all exemples i saw were using metamodel.Tympan
See datanucleus.svn.sourceforge.net/viewvc/datanucleus/test/… for some tests we (DataNucleus) use for string-based criteria; obviously you lose the refactor-capability by using strings, but people should be free to chooseMaxinemaxiskirt
I use the JPA 2.0 / JPA 2.1 criteria API extensively to generate simple as well as relatively complex queries. I have not yet found anything which can be termed, "heavy" and / or "over-complicated". The only irritating thing is that it is not always possible to correctly predict the SQL statement which is going to be generated based on a given criteria query, the behaviour is provider-specific in some situations (the same thing applies to JPQL as well). Thus, one always has to carefully observe the generated SQL statement(s).Blatant
W
9

I can only provide a biased opinion, since I am the maintainer of Querydsl, but I think that both Querydsl and Spring Specifications are mature enough. Both provide a thin layer on top of JPA 2, Querydsl provides a fluent DSL for query construction and Spring Data patterns for DAO/Repository construction.

The expressivity of Querydsl is comparable to HQL/JPQL.

Here are a few JPA 2 Criteria queries and their Querydsl versions : http://source.mysema.com/forum/mvnforum/viewthread_thread,49

We provide fast bug fix cycles and responsive support in our forums. The Querydsl team cooperates with Spring, DataNucleus and other parties to improve the state of typesafe querying in Java.

Whirlybird answered 7/5, 2011 at 14:13 Comment(1)
BTW, Spring isn't a specification.Kelpie
M
9

No, don't like it, due to the lack of expressability and fluency in the API. Yes QueryDSL does the same in less code, and more naturally. For that reason we've taken the same route for JDO's own typesafe query API, comparing it to JPA Criteria https://datanucleus.wordpress.com/2010/11/09/jdo-typesafe-vs-jpa-criteria/

Maxinemaxiskirt answered 6/5, 2011 at 9:10 Comment(0)
W
9

I can only provide a biased opinion, since I am the maintainer of Querydsl, but I think that both Querydsl and Spring Specifications are mature enough. Both provide a thin layer on top of JPA 2, Querydsl provides a fluent DSL for query construction and Spring Data patterns for DAO/Repository construction.

The expressivity of Querydsl is comparable to HQL/JPQL.

Here are a few JPA 2 Criteria queries and their Querydsl versions : http://source.mysema.com/forum/mvnforum/viewthread_thread,49

We provide fast bug fix cycles and responsive support in our forums. The Querydsl team cooperates with Spring, DataNucleus and other parties to improve the state of typesafe querying in Java.

Whirlybird answered 7/5, 2011 at 14:13 Comment(1)
BTW, Spring isn't a specification.Kelpie
K
5

I use JPA criteria builder intensively. I use the metamodel, type-safe variant, but that isn't the only option. If you want to compare JPA to other frameworks, don't count the fact that you need to generate metamodel classes. You don't, for the same functionnality, only for added-on benefits. I wouldn't go back to any non-type-safe approach, though.

When you get used to it, it's quite simple to use, and still powerful.

One added benefit: it's standard. As in: multiple experts from different organizations agreed on it. The quality of the specification is certain, and it's still evolving. And you get multiple implementations (really, at least two of them being used in the most popular application servers). You don't get that if you take a random framework, which may or may not stand the proof of time.

Some examples from JPA2:

Root<Person> personRoot = query.from(Person.class);
Path firstNamePath = personRoot.get(Person_.firstName);
Predicate firstNamePredicate = criteriaBuilder.equal(firstNamePath, "Roger");
query.where(firstNamePredicate);

You could squeeze all of this to one line, but I mostly choose not to do it to get 100% clear code and 1 statement per line.

Kelpie answered 5/4, 2012 at 7:44 Comment(21)
Querydsl is actually very typesafe - your example is just how you construct named alias - obviously, the name is string. But the type is QPerson which is as safe as you get. JPA is standard, indeed. That also means it can evolve, but hardly change for better if they made a mistake already. Comparing Querydsl and JPA Criteria API, I choose Querydsl any time. They changed their API a lot, along with package names from v3 to v4. Result is fluent API even closer to SQL semantics (starting with "select what") - kind of change we simply cannot expect from JPA, be it good or bad.Disinclined
Thanks for your comment, I'll update my answer. Still not a standard while not offering added value in my opinion. Vendor lock-in, no better than using hibernate APIs vs JPA. I wouldn't recommend QueryDSL to anyone, except for pure queries, outside of OO code (super-JDBC vs ORM).Kelpie
It is matter of taste to a degree, I use Querydsl over JPA and would never go back. More fluent, more readable, more type-safe, and in our projects it already paid back big time. I don't know how good/rich metamodel of Criteria API is, but Querydsl metamodel is very powerful too which becomes handy when you have some universal rich table component with filtering/ordering/pagination over many/any query with joins. I've been using it for three years and I'd recommended it any time. It virtually never let me down and even made me feel happy. Not very common with other libs. :-)Disinclined
Taste matters can often be rationalized by comparing facts. Facts are, JPA is standardized and has multiple implementations. Other fact: I didn't see any argument making me think that there are killer features in Querydsl that aren't standardized in JPA. Another: JPA is a spec, and as such has been discussed by multiple parties rather than by a single fast committer. Still another: QueryDSL did change incompatibly in the past. Almost fact: JPA will be there in 5 years, nobody knows for QueryDSL. JPA is well integrated in Java EE. And so on...Kelpie
Facts like "JPA standard, multiple implementations" are not in conflict with Querydsl that is thin layer over JPA. Fact is, it significantly simplified our code, which is a killer feature for me. More facts: Changing JPA provider is hard especially when you have tricky JPQL already (tried it). JPA is standard, so was entity beans. JPA emerged from non-standard projects. Selected facts sometimes hide more, especially when comparing on different levels. It's not Querydsl vs JPA - it's merely Querydsl+JPA over JPA, or maybe Criteria API vs Querydsl. It's not like you loose all JPA or what.Disinclined
Changing providers: done that, multiple times (Hibernate, EclipseLink, OpenJPA). Stick to the standard and it will keep working. Work like a cow-boy and don't know the spec, not understanding its nature, and you'll have seemingly-subtle problems. By using a non-standard "thin layer", you loose your vendor-independence: bound to the only implementation of QueryDSL, no specification to differenciate bugs from implementation details, etc.. Still didn't see any argument that'd make QueryDSL "easier". So, let's stick to facts: it's arguable that QueryDSL is better, but it isn't standard.Kelpie
It seems this got personal and full of assumptions. I'm not assuming anything about how you use JPA, but I sure respect you for reading and memorizing ~600 pages of the spec. I switched providers for simple cases too. But once we tried to switch EclipseLink to Hibernate and for the same JPQL we got completely different results and even broken SQL. Either it should have been invalid JPQL in the first place or working on both. Querydsl had nothing to do with it as you tried to imply.Disinclined
Nothing personal at all, no assumptions about you. Maybe out of topic, for sure. Let's stick to facts, really. For any given JPQL, it could either be valid or not (per specification). The developer is responsible for writing valid queries. Some invalid queries could pass through on some implementation, that's right. Some things aren't specified (and as such, you can't rely on them). Some things are cleary specified and a dev responsiblity (e.g. bidirectonal rels). BTW, I have 0 lines of JPQL in productions, everything in Criteria (compile-time safety, much harder to write bad queries, etc.).Kelpie
Anyway, I didn't imply that Querydsl broke your app. Or isn't that what you meant? I'm really not sure. I do say that JPA has a clear specification, allowing to know how implementations must behave. Switching implementations does work for sure (or please prove me wrong). I won't say that I never broke something, but it's always been my fault ;-) tl;dr: We've been nitpicking, but I still don't see any factual advantage in QueryDSL (i.e. more than saying that it's easier without proving it). If they are both capable but one is an established standard, I know which to choose for sure.Kelpie
Fair enough. :-) Regarding my problems, imagine a Dog having @ManyToOne to Breed, mapping as simple as possible. When I select d from Dog d where d.breed.name = 'collie' I get back proper resuts (1 dog called "Lassie", unsurprisingly). When I turn this to delete delete from Dog d where d.breed.name = 'collie', Hibernate produces delete from Dog cross join Breed breed1_ where name=? which fails (at least on H2), not to mention both tables have name which is not distinguished so it's wrong even if it magically worked. If where clause for delete does not allow this... (next comment)Disinclined
...I can't find it in the spec. I'm not saying it's not there. I also know how to rewrite this with subquery to make it more vendor neutral. But this simple traversing across single many-to-one field at least demonstrates how hard JPA is even for simple cases. It's very easy to do naive mistakes(?) like this and very difficult to find them in spec. I learnt to search for "not supported" in spec, that way I found why count doesn't work for some selects ("The use of DISTINCT with COUNT is not supported for arguments of embeddable types or map entry types.") but there is nothing about delete.Disinclined
To me, if it's still present in Hibernate, it's a bug, even if partly documented (for HQL though). Spec doesn't give any provision for this because it just should work, as described in JPA spec 2.1 §4.10 describing bulk updates, this paragraph referring where_clause described in §4.5. You didn't find it because there is no restriction telling that it shouldn't work. If you want a nice illustration of a big positive point of having a spec, file a bug in Hibernate mentioning this.Kelpie
We could even file another bug for the JPA TCK to check that it works, and that'll make sure all implementations will have to implement that correctly.Kelpie
So, basically, you found a bug. Not a JPA bug (pretty sure it works well in other implementations), but an Hibernate one. Please also note that, in this specific example, it would be more in the JPA / ORM (note the O) spirit to rewrite this as this: "DELETE Dog d WHERE d.breed = :breed" and pass a Breed instance as parameter. That will work, regardless of whether the mentioned bug exists.Kelpie
I guess we should move to a dedicated question if you want to investigate this further.Kelpie
BTW, this provision seems to be gone in Hibernate 5 (as it should): docs.jboss.org/hibernate/orm/5.0/userGuide/en-US/html_single/… . So, I'm guessing the bug you found is gone ;-)Kelpie
As I read the spec I also believe it's a bug and I'll try to file an issue for it. I tested it just today (again) with the freshest 5.0.6.Final of their ORM. I can rewrite it to d.breed= in this case (though I have to get the specific breed first which likely increases roundtrips to DB) but I can't rewrite it like this if I used something like d.breed.name like ... or any other condition implying multiple breeds. In any case I'm glad we're parting in peace. :-)Disinclined
Seems to be a real bug, as it is against their newest doc as well as the spec. I'm willing to bet you won't have a db roundtrip: 1) you should probably have an object instead of a name to begin with (I'd need to see your use cases, but that's the typical way) 2) a central piece of jpa is caching, which I suppose you enabled anyway, and there is a big chance that you hit the cache for such queriesKelpie
Alternatively, you can use portability to your advantage: just try with EclipseLink, I'm willing to bet it will work quite well.Kelpie
Bug already exists hibernate.atlassian.net/browse/HHH-9711 I added a comment there. Thank youDisinclined
Nice :-) Voted for it.Kelpie
D
4

I use JPA2 in my projects and always found Criteria API a bit overcomplicated especially for building simple select statements with a few where conditions.

So I decided to go on using JPQL queries. Maybe the Criteria API has its strength with more complex queries (besides some other advantages).

Dynameter answered 6/5, 2011 at 8:52 Comment(3)
Have you considered the solutions of Querydsl or Spring SpecificationsTympan
@Sebastien: No, JPQL always fit my needs (up to now). Can you provide a link to both frameworks. I will have a look at it.Dynameter
You can find the links on this page i posted with explainations: blog.springsource.com/2011/04/26/…Tympan

© 2022 - 2024 — McMap. All rights reserved.