views:

3732

answers:

20

I would like to know which are the weak points of Hibernate 3. This is not pretended to be a thread against Hibernate. I think it will be a very useful knowledge for decide if Hibernate is the best option for a project or for estimating its time.

A weakness can be:

  • A bug
  • Where JDBC or PLSQL are better
  • Performance issues
  • ...

Also, can be useful to know some solutions for that problems, better ORM or techniques, or it will be corrected in Hibernate 4.

For example, AFAIK, Hibernate will have a very bad performance updating 10000 rows comparing to JDBC in this query:

update A set state=3 where state=2
+11  A: 
  1. Hibernate lets you access the underlying JDBC objects, so if there are things you prefer to do in raw JDBC you can (in the same transaction).

  2. Hibernate supports bulk updates like your example, and they are done directly in the database.

If you are starting from scratch, hibernate will be great for your project. (Hibernate can be a little difficult if you are reverse engineering an existing db). The philosophy is to let hibernate do everything, and only if you find a bottleneck and find Hibernate is doing less than optimal things, you can try to tweak it or write your query in plain JDBC.

I think for general projects, Hibernate has no weaknesses against JDBC. And it has several advantages.

  • Your app will be cross RDBMS.
  • Your app will be safer (Hibernate uses internally prepared queries).
  • 99% of the time, your app will perform better.
flybywire
+5  A: 

There are some design trade-offs when you're using Hibernate.

For example you cannot be sure that an object is fully initialized after its constructor is called. Hibernate mandates a default constructor and will initialize your object with successive setter calls. This makes checking invariants harder as you cannot not simply say after the constructor is called I can check the invariants. This has a drastic impact on the domain object design.

Thomas Jung
While I'm not arguing that using Hibernate comes with design trade-offs (which BTW is true for any framework), your example is questionable. You can always make the no-arg constructor private for Hibernate and have another (public) one for your API. You can also add an initialization callback if you need to perform certain actions after object has been fully loaded.
ChssPly76
So what was a constructor is this strange design in your class. That's the whole point. Things get more complicated and harder to reason about.
Thomas Jung
I don't understand the "whole point". Are you saying that every class should only have a single constructor that would initialize all the fields? That seems like a pretty restricted approach. The "strange design" as you've called it was not exactly invented by Hibernate; it stems from the javabean spec and is rather common in the UI world.
ChssPly76
This is something that always bothered me. All of my domain objects MUST have a zero-argument constructor. If I want to do any sort of non-persistent initialization, I have to either do it explicitly after Hibernate retrieves the object, or I have to hook some sort of Hibernate interceptor in, which is really tricky. I really wish Spring and Hibernate especially could play nicer with this issue.
CaptainAwesomePants
@CaptainAwesomePants - I've yet to see a case where having a private no-arg constructor is a huge issue; so unless you can provide an example to the contrary, that's not a valid argument. Post-load entity initialization can either be done in dao / service itself or you can configure a **single** listener (takes 4 lines in cfg) to invoke some kind of "postLoad()" method in all of your entities (if defined). If you need this on a regular basis, however, the problem likely lies with your architecture.
ChssPly76
@ChssPly76 Hibernate specifically recommends that it NOT be a private constructor. http://docs.jboss.org/hibernate/core/3.3/reference/en/html/persistent-classes.html#persistent-classes-pojo-constructorAlso, I'm not sure why the requirement that I modify my domain objects to suit Hibernate isn't a "valid" concern.
CaptainAwesomePants
For runtime proxies only (not that common, can be circumvented with javassist nowadays). As far as "requirement that I modify my objects" goes, it's kind of like "requirement that I prefix my getters with 'get' for object to be javabean". Yes, it's a requirement; that's the price you pay to enjoy all the benefits of given framework. It's not a valid concern to me because I don't see any problems with it. Compare that with madness of the original EJB spec.
ChssPly76
@ChssPly76 - you are exactly spot on with all of your comments here. It is a framework - that comes with pluses and minuses, and if you need to do something to all of your domain objects, you are likely putting too much logic into your domain objects, in my experience.
aperkins
@ChssPly76 - Let's make up a simple example. You have a class A{int x; int y;} and you're invariant is that x + y > 0. So with an constructor you can say: A(int x, int y){assert x + y > 0; }. Try to implement the same invariant with hibernate.
Thomas Jung
@aperkins - "you are likely putting too much logic into your domain objects". Just from one source: "A business object often encapsulates all of the data and business behavior associated with the entity that it represents." (http://en.wikipedia.org/wiki/Business_object_%28computer_science%29). You're suggesting a anemic domain model (http://martinfowler.com/bliki)./AnemicDomainModel.html)
Thomas Jung
@Thomas - is class from your example immutable? If not, your assertion in constructor won't do you much good. If it **is** immutable, keep your public A(int x, int y) constructor and getters; add private no-arg constructor and setters for Hibernate and you're good to go. You seem to think that validation has to always occur - and that's not true. Data you read from the database had to have been persisted previously and thus have already been validated (when your object was created initially).
ChssPly76
@ChssPly76 It is mutable. So you have to check the invariant after the constructor and all method calls. When you're creating an instance A(-1, 2) with hibernate that is valid, the problem is where to put the invariant checks. The invariant depends on both properties. The simple solution A{ setX(){check(...)} setY(check(...)} will not work. It depends on the method call order. (When a class is implemented you do not known your client so it is a defect to write special code for hibernate. This is a trade-off you have to make here.)
Thomas Jung
@ChssPly76 - I could add a question and you could then answer it with all your suggestions. I don't see how you're not ending up with a lot of code (as I did) for a relatively simple problem compared to good old java (without hibernate).
Thomas Jung
@Thomas - you've lost me. What does any of this have to do with Hibernate? Show me your class written in "good old java" such that iy satisfies all your requirements and I'll show you what needs to be done to have it mapped in Hibernate.
ChssPly76
@ChssPly76 - To keep it simple without setters: `class A { int x; int y; A(int x, int y){ this.x = x; this.y = y; if(x + y < 0) throw new IllegalArgumentException(); } }`Valid:`new A(-1,1);`Invalid:`new A(-1,0);`
Thomas Jung
But it's pointless without setters. That's why I asked whether your class is mutable and you said "yes". If you don't have (need) setters and thus your class is immutable, declare private constructor and private setters (you don't even need the latter if you annotate properties directly) for Hibernate and you're good to go. If your class **is** mutable, I want to see your setters and how you do your validation. It's probably a good idea to move this into a separate question as you've suggested; this thread is way too long now. Please link to it here if you do so I can find it. Thanks.
ChssPly76
I think, you did not get the problem. Hibernate cannot call `a = new A(); a.setX(-1); a.setY(0);` if the invariant check (`if(x + y < 0) throw new IllegalArgumentException();`) is in the setters. How do I check the invariant after the object is constructed?
Thomas Jung
Thomas, the problem only exists in your imagination :-) If **you** need to have public setters, **you** need to figure out how to do the above validation (which I imagine you'd do in some kind of `validate()` method invoked after all the setters). If you do **NOT** need public setters, you'll create privates ones for Hibernate's use. Your object does **NOT** have to be validated after being loaded / populated by Hibernate because this data has **already** been validated when it was persisted. Either way, there's no need for **Hibernate-specific** validation.
ChssPly76
@ChssPly76 Question: http://stackoverflow.com/questions/1624392/check-invariants-in-hibernate-mapped-classes
Thomas Jung
@ChssPly76 - it is, as Thomas said, a design *trade-off*, not necessarily a fatal flaw in Hibernate. I for one can live with it, though I wish I didn't have to (I'd love (N)Hibernate to support constructor injection).
Jeff Sternal
+6  A: 

this comes to mind.. The horrors!

disown
+3  A: 

I have been using Hibernate for over 3 years on a project, and I can say that I love it. Yes, it has it's drawbacks. Yes, it does some things inefficiently. However, the few that it does can usually be tweaked out, and in general, especially if you are designing the database yourself, it is wonderful. I have used it for some small personal projects where I was storing data in an embedded Derby database, and I have used it in my current enterprise system I work on.

The core of Hibernate is it is an abstraction - it frees the majority of your code from having to worry about the database, and allows you to look at the objects themselves, rather than the database calls.

If you are thinking about using Hibernate, I would strongly recommend the book Java Persistence with Hibernate, written by Christian Bauer and Gavin King. It is not an easy read, very technical, but it covers just about everything there is to know about Hibernate 3. I have a copy near my desk at all times, and it has proven invaluable through my usage of the library.

aperkins
+3  A: 

Its major weakness is that layers such as those "shield applications from underlying DBMS specifics", but that they can only manage to do so at the expense of taking away even more from the power of relational technology for the application, than the average SQL DBMS already does by itself.

As a prime example, try and find one such layer that doesn't enforce the fallacious and unnecessary notion of "identity" upon the underlying relational stuff.

That is not a Hibernate 3.0 issue, that is not a Hibernate issue alltogether, that is an issue of people writing and people using such layers who just don't understand jack shit about the power of the relational model.

EDIT (elaborating on "fallacious notion of identity")

A database is a set of statements (or "assertions") of fact. E.g. "Mount Kilimanjaro is 5990 metres high" and "I have climbed Mount Kilimanjaro in august, 2008". No database has any need for 37-digit "mount identifiers" in order to be able to (A) represent that information, and (B) allow any user to work with and manipulate that information.

Erwin Smout
Can you elaborate on "fallacious notion of identity", please?
ChssPly76
Ooh, nice. So forgetting the Hibernate, JDBC and everything else for a second; how do I find out what mountains I have climbed in August, 2008 that were above 3000 meters high?
ChssPly76
I can't see any valid arguments here, @ChssPly76 is apparently a Hibernate "apologist" (he's chimed on on several of my Hibernate questions) notwithstanding, his points and counters are all valid; @Captain... et al should all try creating a Hibernate/JPA hybrid that just allows the programmer to do their own design and see how more inherently difficult and endless that venture becomes.
non sequitor
@non sequitor - answering Hibernate questions on SO hardly makes me its apologist. I am well aware of quite a few shortcomings Hibernate has; I'm not listing them as an answer in this thread because it'll take too long to explain them to the general audience and the end result would most likely be unappreciated due to their somewhat esoteric nature. And if you didn't want me "chiming in" to your questions, you had but to ask.
ChssPly76
@ChssPly76 :( oh you take this too seriously (chiming in was in no way pejorative -- might a British cultural thing since I was born whilst my country was still a colony). But I am interesting in these esoteric thoughts of yours(as you definitely know more about it than I) but I can't figure out the forum for it. If you have any suggestions let me know. I also have something to run by you concerning that other question I had where you figured I would have to roll out my own persistence provider, I'll post the question.
non sequitor
Sorry, but it's pretty rare to see a relational data set of any complexity that doesn't have a bunch of id fields, notwithstanding the presence (or lack of) an ORM layer.
CurtainDog
A: 

Hibernate always has and probably always will kind of suck at surprisingly obvious things like Java enumerations. To store an enum, you have to go through all sorts of hoops and custom handling classes and whatnots. They should be as simple as integers or strings (depending how you'd like to store them), but for some unknown reason, they're not.

Also, tuning Hibernate can be rather difficult. Like Rails, it's great to get going, but when it comes to fine tuning, it's not really your friend (although their SQL debug output is fantastic and very useful). Sometimes you want wait an HQL query to do a join, in other cases you want it to retrieve everything from cache, and it's hard to specify when you want what to happen.

CaptainAwesomePants
I'm sorry, but this it's hard to take this rant seriously. Enums are mapped via a single annotation: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e342; Hibernate does not cache **ANYTHING** you didn't explicitly tell it to and tuning Hibernate-based app is no different from tuning JDBC based app. This goes to show, however, - along with some other answers in this thread - that Hibernate's biggest "weakness" is somewhat steep learning curve.
ChssPly76
I'll agree with you that complaining about how it caches is probably unfair, so I removed that bit. However, I don't use annotations: I use hbm.xml files. I can't find a single reference to enumerations anywhere in the Hibernate core documentation to enums. If you know of a way, though, I'd love to know about it. http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/
CaptainAwesomePants
enums - like annotations - were introduced in 1.5; hence the lack of **direct** support in XML mappings. You **can** reference the new EnumType from .hbm.xml, though: http://stackoverflow.com/questions/1561001/hibernate-how-to-use-an-enumeration-as-maps-key/1561639#1561639
ChssPly76
I am sorry, but I have used enums in hibernate - they are easy to use. I have also done fine tuning of database queries. I agree with ChssPly76 that this is not any harder - and is often easier - than doing raw JDBC. Why easier? Because you often can find the exact queries that are causing the problems, and start the tuning there, and the rest of your application is not worried about persistence, but instead objects, which is much more natural in Java.
aperkins
I'm sure you're right, but would you mind telling me how to do use enums in Hibernate without annotations, or point me to documentation of such a feature?
CaptainAwesomePants
If you are using Enums, you are clearly using Java5 or later, so why the resistance to annotations? As for how to do them with XML, I am not sure - I do everything with annotations.
aperkins
@CaptainAwesomePants - I've provided a link to my other answer above which shows how to use Enum in hbm.xml mapping. You'll declare it as `<property name="myEnum" type="org.hibernate.type.EnumType"/>`; you need to have hibernate-annotations.jar in your classpath for that to work but you do **NOT** need to use AnnotationConfiguration.
ChssPly76
+72  A: 

Hibernate is really great but it definitely needs some skills and experience: knowledge of ORM concepts, mappings and relations are welcome, understanding of how the Session works, understanding of more advanced concepts like lazy-loading, fetching strategies, caching (first-level cache, second-level cache, query cache), etc.

Sure, when used correctly, Hibernate is an awesome weapon: it's efficient, it will generate better SQL queries than lots (most?) of developers, it's very powerful, it has great performances, etc. However, I've seen many project using it very badly (e.g. not using associations because they were scared to "fetch the whole database" and this is far from the worst horror) and I'm thus always a bit suspicious when I hear "we are doing Hibernate". Actually, in the wrong hands, it can be a real disaster.

So, if I had to mention one weakness, it would be the learning curve. Don't underestimate it.

Pascal Thivent
Agreed on the learning curve. As far as being "real disaster", sure but anything in the wrong hands can be. I saw some JDBC-based and Torque-based applications that were **FAR** worse than ugliest stuff I've seen done with Hibernate.
ChssPly76
Well, there is indeed no limit in atrocity but this is not worth a contest :)
Pascal Thivent
Your weakness is not a weakness of _hibernate_, it is a weakness of all enterprise grade, transparent persistence ORM's. JPA based ORM frameworks will have the same weakness.
Michael Wiles
@Michael I agree... but I'm not sure to get your point. Did I say that it was specific to Hibernate?
Pascal Thivent
and it has quiet a few very annoying bugs you will encounter when pushing it to the limit.
Chris
@Downvoter Downvoting without a comment is so lovely... Care to explain what is wrong with this answer?
Pascal Thivent
I would definitely agree about knowing ORM concepts. Even better, having to write your own ORM will teach you a lot about the good things about Hibernate. :-)
staticsan
I wish I have read this before choosing to use Hibernate
nimcap
A: 

"So forgetting the Hibernate, JDBC and everything else for a second; how do I find out what mountains I have climbed in August, 2008 that were above 3000 meters high?"

RESTRICT(JOIN(MOUNTAINHEIGHTS,MYCLIMBS),AND(EQ(CLIMBDATE,...),GT(MOUNTAINHEIGHT,___)))

in which ... stands for the appropriate value selector for "august 2008", and ___ stands for the appropriate value selector for "3000 metres height".

MOUNTAINHEIGHTS and MYCLIMBS are the relvars ("tables" if you need that term).

And the join between the two works because obviously, (a) both have a mountainname, and (b) the database is such that there cannot be any climbs of a mountain that does not exist (assuming that if a mountain exists, its height is known).

INCIDENTALLY

"his points and counters are all valid".

I have not seen any "points and counters", and therefore must admit to the truth of this statement : every predicate is always true over the empty set.

Erwin Smout
Are you sure there are no two mointains with the same name?
meriton
You do realize that `mountainname` you're referring has to be a primary key in your `mountainheights`, right? And that you can very much map that in Hibernate? Surrogate keys have some very important advantages but are not by any means **required**.
ChssPly76
Fair enough, but my understanding is that the case of composite keys gets way more problematic to map. So my understanding is that Hibernate and the likes are a practical obstacle to composite keys, because composite keys ALSO are a natural feature of relational designs.(And in the language that I use to identify the mountains in my climbs database, yes I am pretty sure that there are no two mountains with the same name. I have seen similar arguments used against names of animal species and such. No agreed-upon scheme exists for unique animal species names ?)
Erwin Smout
I thought of one of the "advantages" of these "fake" identifiers :The owner of the account with ID 7 is the person with ID 9.The owner of the account with ID 3 is the person with ID 1;The name of the person with ID 1 is Erwin Smout.The name of the person with ID 9 is ChssPly76.The balance of the account with ID 7 is 5000000 USD.The balance of the account with ID 3 is zero.Updating the names of the persons with IDs 1 and 9 by simply swapping will make me the happy owner of YOUR 5000000 USD.I'm not joking. I have actually seen a fraud based on this very weakness.
Erwin Smout
@Erwin - "more problematic" != "impossible". You **can** use composite keys and map associations over composite keys. Discussion on surrogate vs business keys is off topic here and has no connection to Hibernate; you can google up a ton of articles showing pros / cons of each approach. As far as your example goes, Mt. Everest is also often referred to as Chomolungma (and that's just in English). Care to work that into your model and see how that is more "natural" and less "problematic" than using a surrogate key?
ChssPly76
@Erwin - I'm sorry but I can't take this seriously. Either you're trolling or you've obtained your knowledge of ORM and relational theory in general from some rather quirky sources. Both cases make further discussion rather pointless. If you're sincere with your account example I would **strongly** suggest you start with a google search on "surrogate key" and go from there.
ChssPly76
The same holds for "impossible" != "prohibitive"."has no connection to Hibernate" : that is the very same thing I said in my first response."Chomolungma" : if my business problem ("which mountains did I climb in august, 2008") does not REQUIRE any need for knowledge of synonyms, then this remark is not a problem.If the business problem DOES require knowledge of synonyms, then that can be solved WITHOUT 37-digit numbers in a way that I have also described for "historical names of countries", and whose description doesn't fit in the 19 characters I have still left.
Erwin Smout
"or you've obtained your knowledge of [...] relational theory in general from some rather quirky sources."Well, like most, at one point in time, I thought I had knowledge about "relational theory in general" just from using an SQL-based system.The knowledge that I have NOW about "relational theory in general" has Chris Date for its source. In case you don'k know : he's the one who cooperated the closest possible way, for decades long, with the very INVENTOR of that theory.That you label that source as "quirky" says averything about yourself and your own utter lack of knowledge.
Erwin Smout
Thomas Jung
+3  A: 

All other issue aside, attempting to optimize performance when working with any ORM involves an extra step because the ORM layer translates your query or criterion into SQL which is then executed. Whereas with a direct SQL approach you can tweak the SQL to your heart's content, in ORM systems, you have to tweak your query and hope it has the expected effect on the generated SQL. In my mind this deficit is far outweighed by the benefits of ORM, but its still a failing in my mind.

Jherico
You have to distinguish between two separate use cases here. When dealing with mapped queries it's reasonably straightforward to deal with optimizations (you don't _hope_ that your program would do what you want after compilation, right? You write it so it would and fix bugs if any. Same with HQL). Dealing with Criteria (or assembled HQL) is indeed more complex but I would argue that it's still not THAT different from building straight SQL from pieces. This is usually reserved for QBE-style queries anyway and thus possible optimization is rather limited.
ChssPly76
As every good abstraction it's leaking. With every nontrivial application you have to pay attention to database performance. The query performance will be not optimal but this can be tuned. For most applications the update and delete performance is sufficient and this removes a lot of sql statements and mapping code. This is clearly the part of hibernate that works very good. The session can defer update and delete statements which can be a performance boost.
Thomas Jung
+2  A: 

I've been using Hibernate for around three years. A few things I've found that are rather annoying are:

  1. It's hard to mix JDBC and Hibernate. They deprecated the connection() accessor. A number of things just can't be done well in Hibernate's HQL.

  2. It's almost impossible to create insert/select statements that select static strings using parameters to prevent SQL injection. At least, I couldn't figure it out. Something like "insert into foo select 'string',bar,baz from myTable". Such things just don't fit into the ORM model.

  3. Hibernate Tools is rather limiting if you want to automatically generate your .hbm.xmls or annotated classes directly. Further, you can't mix them to generate the annotated classes and augment that with .hbm.xml stuff, like changing the default key generation method, adding validation, changing select and join modes (to retrieve child notes in a single select instead of hundreds of separate selects) or adding filters.

  4. There's no good way to mix straight SQL and mapped object access via HQL. Sometimes expressing a query in HQL or Criteria is easier, but you need to wrap that as a sub-select in native SQL due to limitations in HQL. It can be done using internal classes and other hackery, though.

  5. Calling non-standard SQL functions in HQL is either impossible or very difficult (e.g. newid() in SQL Server.)

  6. Error recovery is rather poor, at least with SQL Server. Connection's are put into strange states and all subsequent operations fail. It's not smart enough to close the connection to reset. You can somewhat get around this using C3PO, bit it's aggravating none the less.

  7. It doesn't seem to handle an entity with a subclass. It seems to map the subclass to the base entity and complain that you've already mapped the entity.

  8. Caching is a blessing and a curse. It sometimes caches aggregate select statements that's obviously uncachable.

So, while I've definitely saved a ton of development time using it, there have been a number of things that would have been much easier using if it weren't around. Overall, it's been a tremendous time saver.

Norman
Comment has no space to address 8 issues, but briefly: (1) has been replaced with `doWork()` in 3.3.2; (3) yes, but tools are to _help_ you not do your work for you - adjust mappings manually after generation; (6) not a Hibernate problem; it relies on underlying connection pool and JDBC driver; other points are either not true or of your own doing.
ChssPly76
+1  A: 

... better ORM or techniques

Ebean ORM is session-less ... I believe this makes it much simpler to use and understand than say Hibernate or JPA. You don't have to worry about Session Management (or its side effects) nor lazy loading (which just works).

You use save() and delete() ... rather than session based merge(), persist(), flush() which is more explicit and gets around issues such as when you only want to flush part of what is in your session etc.

So, if you want an easier learning curve then Ebean ORM is definately worth a look.

If you are into performance then I'd suggest "Partial Object" support is also worth looking into (Ebean has partial object support and incorporated it into it's query language).

Rob
+1 Ebean seems like an interesting project! Didn't know about it.
Subtwo
+14  A: 

I've come off a large project using hibernate and here are 3 weakness I think hibernate has

1. Poor object inheritance handling and an aversion for instrumentation

When you load an object in hibernate (and you've used load so it is a proxy), if that object is in reality (as specified by the database) a sub-class of the one you loaded, hibernate will not load the real type of the object. You will get it a proxy on the type you asked for when you loaded (and not a proxy on the actual type of the object). so

A a = (A)session.load("id", A.class);

Even if on the database that id is of type B (a subclass of A) you will still only get a proxy onto A (and not B). In order to get the real type you have to do another step.

This same thing occurs when trawling an object tree.

Fortunately though, by using instrumentation the trawling issue is solved in that if once an object is instrumented then when trawling the object tree you will get back the real types (except when the object is pulled from a many-to-many collection though).

Instrumentation does not solve the load anomaly still exists, instrumentation could be used to solve this problem as well.

2. Save a large new object model in one go

We had several processes which generated a large amount of new entity objects (persistent objets) and I then needed to save all these. I could not simply call save on the source object and expect everything to be saved. You might ask why I didn't setup the cascading to do this, yes, I could setup the cascading for one of the use cases but then when I ran another one of the process that created new objects that would need its own cascade structure. So I would like hibernate to have a facility where I can arbitrarily save a set of objects. The work around for this is that I reflectively trawled the object tree calling save on each object, and I had to do this in a particular order. The facility I'm looking for here is called persistence-by-reachability.

3. Specify the boundaries of what I want prefetched on a task by task basis

I know with hibernate you can prefetch a collection via a keyword in a query, often that is not sufficient. Say you want to work with a bunch of related obects, you'd want to have them all pre-fetched up front so no slow down and inefficiency later, furthermore, there may be multiple sets of objects for the various tasks you're looking to perform, all with their own "fetch profile". iow, for this task I want these objects pre-fetched, for that task I want those.

Fortunately, number 3 is slated for release in hibernate 3.5 and is known as "fetch profiles".

Michael Wiles
See my aswer for comment on 2.
Ondra Žižka
A: 

I think what you care right now is whether you should use an ORM or not.

In general terms, Hibernate is a drag if your application logic is very simple in measured in amount of entities and their relationships.

When you can use ( as you mention )

update x where y = z

or

select * from x

it is better to use direct SQL or some intermediate step.

When your entities relationship are too complex ( like

select x.a, y.b from j,k,l,m,x,y where j.id = k.id and k.id = x.id and ..... )

it is better to use an ORM.

See this other answer for more details on that

OscarRyz
Note that Hibernate does support [bulk SQL-style DML statements](http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html#batch-direct) performed via HQL.
Pascal Thivent
A: 

Hibernate is superb and has allowed me to finish mega-projects.

I dislike the fact that since it automates and hides stuff, the average joe developer will sometimes produce horrible N+1 and other horrendous inefficiencies in his application, something that would naturally not happen when using plain JDBC.

I also dislike the default constructors and non final fields restriction.

cherouvim
+1  A: 

When using hql or criterions, hibernate needs to known how objects are associated together. This can gets tricky if you want generic entities or split your entities in different projects that don't know each others.

For example, say you have a core module that handles events and events are stored in the database. Over that project, you build an subscriber management module and link events to subscribers. Since the subscription management module depends on the event handling module, you can have a list of events in the subscriber entity but you can't have a subscriber property in the event entity since Event can't depend on Subscriber.

You can get the list of events for a specific user easily by calling something like subscriber.getEvents() but if you want to query (using hql) for events that are associated to subscribers living in some city, it gets complicated. Using simple SQL, it would be a rather simple query with a join on the join table. Note that you can always fall back to SQL when needed.

In opposite to what other are saying, I think that inheritance in hibernate is great. Especially when you consider how complex that can becomes. However, you will need to read the doc and experiment with it to really master it.

Other than that, hibernate is a great tool. I would never start another project using only JDBC.

Manuel Darveau
+1  A: 

I found that Hibernate is generally NOT good for batch tasks. I prefer to do them in pure SQL or PL/SQL, evt. with TRIGGERs. Then I call few lines in Java and tadaa - it's done, with no transaction stuff, consistency problems, etc etc.

I have converted a simple application (properly indexed and mapped) to that approach, and it was 15-times faster after that.

Ondra Žižka
+1  A: 

It seems to have weakness around proxies http://blog.bolkey.com/2009/05/hibernate-datanucleus-r1/

+2  A: 

It doesn't seem to be very well supported in terms of fixing bugs. This link put me off http://www.theserverside.com/news/thread.tss?thread_id=59963#334556

A: 

Lack of foundation? Here is my experience with TopLink (and I wonder if Hibernate is any different):

  1. Extract a subset of attributes from one relation. Really easy mapping; move on.

  2. Extract data spread between two relations. TopLink: "here is dozen-something different types of relationship..."

Game over. I'd rather learn 7 classic relational algebra operations, rather than 13 proprietory ad-hock association types. I'm a little facetious, of course: I knew relational algebra and SQL pretty well at the time, so there is really little motivation to learn an alternative way.

Tegiri Nenashi
A: 

ORM is ill-suited for tasks where you need to query large, relatively simple datasets and performance matters. The more performance matters, the less useful Hibernate is.

Example - the Hibernate session. Sometimes I just need to load a huge amount of data from the database and process it a row at a time. Once I am done with the row, I will never access it again. Hibernate adds every row into the session and then checks whether I the object was modified, slowing my code down and running out of memory. If I do not want this behavior, I have to Session.evict the objects, or Session.clear - in other words, I am forced to do extra work to stop Hibernate from doing something I do not care about.

Another example: When displaying data in a table, you would like the user to choose which columns they want to see.

How do you make Hibernate load only those attributes of the objects that are actually going to be displayed? Hibernate wants to load the full object, but that means you transfer potentially a lot of extra data that is not needed. This is not necessarily an issue with Hibernate, this is a problem of OOP, which is ill suited to efficiently store certain data structures.

Roman Zenka