Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

+1 for Hibernate. Everyone starts out hating it. The learning curve is steep and unforgiving. But it can do roughly everything SQL can plus everything you would want from an ORM.

For the few that actually read the manual, there's strongly typed Criteria queries that have the full power of HQL. Which is basically DB agnostic SQL with a few really advanced features removed. There's also lazy loaded collections, caching, change auditing, HBM2DDL validation, mappers that can transparently encrypt/decrypt, calculated columns (calculated by Java code, not SQL), and automatic versioning. All database agnostic.

And with the right settings, it's blazing fast. Maybe only 30% slower than native SQL.

We use all MetaModel strongly typed Criteria queries and it's given us the Holy Grail. Any table or column type or name we change is a compiler error until all the queries are fixed. This has allowed us to rewrite large parts of the schema with confidence that our queries won't break. The ultimate bane of working in SQL without an ORM



LOL, I love the way you describe that... "for the few that actually read the manual". That has basically been my experience as well, and the ones that complain the loudest are the ones that refuse to read and understand what is actually happening.

I've also run into a lot of people that loved it at first and then hated it when it first went into production because they didn't read the manual and didn't pay attention to what kind of queries they were actually generating.

I get the feeling that this is why there is often a lot of angst against it from the operations folks.


Yes absolutely.

Hibernate is a microcosm of Java. If you read the manual things are fine, but it's not designed to be "wingable". It abstracts away enough of the DB that you need to understand the magic or you'll make massive blunders that haunt you later.

Given that maybe 10% of devs read the manual for anything after leaving school there's a lot of Java and Hibernate haters


I'm still at the "hating it" stage, but most of my Hibernate experience has been with older versions of Java (5 & 6), or with trying to deal with other people's HQL sprinkled all over. It's a lot of rope to hang one's self with, IMO. Not that native SQL isn't, but there's something to be said for an enforced separation of concerns that I feel like Hibernate breaks a little too often.


My most useful suggestions to less hate:

Turn on the MetaModel code generation stuff. Use Criteria with strongly typed queries for everything that's not a simple find. Much less potential mistakes in combination with validation.

Always turn on HBM2DDL validation! Without this you won't know if there's a problem between entity->table mappings until a query explodes.

For the same reason, don't use HQL or Raw DB queries. You lose training wheels Hibernate is meant to give. In the same vein always use MetaModel strongly typed Criteria .get() syntax. Column/table name strings are evil, you lose type safety.

Turn on collection lazy loading. Otherwise N+1 queries will be everywhere. Beware future detatch() advice when doing this, you will need to trigger the load before detaching if you want that collection to be there.

Use a JDBC proxy to monitor for slow transactions and pretty print generated SQL if needed.

Be very careful with Hibernate lifecycle. It normally returns object proxies, the objects it returns to you are not of your actual class. They have magic in them that can explode if you continue to pass the POJO around after the transaction is complete or session flushed. Rule of thumb, detatch any entity you're passing to a different method.

Again with lifecycle... Be aware that asking for the same object twice will not give you a copy. It will give you the same object! Reference and all! This is another reason to detatch. You don't want people modifying POJO's built by Hibernate, they're magically linked to actual DB data.

Use Identity Type = Sequence. It's less dumb than normal auto-increment PK

Never use your entity classes directly in REST endpoints. You're in for a world of pain when refacgoring DB columns when it also changes your endpoints. Use something like MapStruct to map your entities to DTO easily.

Use Lombok to greatly reduce the POJO insanity of entity classes.

Be very very careful with session.clear() . Unless you 110% understand it, don't use it.

Be careful when trying to serialize hibernate entities. If you have a circular reference between two entities (bidirectional parent child for instance), Jackson and GSON will recurse infinitely. To prevent this, use their annotations to prevent serializing in the direction that makes less sense. Mapping to MapStruct DTO's before REST will allow you to directly prevent this.

For things like PK, use primitive types to prevent hibernate from inserting nulls. This is kinda a hack, but nice if 0 is an acceptable default value which it often is.

Enable code generation style dirty checking. Otherwise, for checking whether child collections and such have been altered hibernate will call .equal(), which nobody ever implements correctly (or at all). Better to use code generation dirty checking mode so hibernate can use magic to check fields for you.

Be aware that hibernate doesn't care if FK's or indexes exist. If you want things to run at realistic speeds, you still need to make these yourself.

We managed to make our entire app, with about 110 REST endpoints, entirely strongly typed Criteria queries. Not a single line that isn't DB agnostic or bypasses hibernate. Trust me, things are much better this way. Once you cross the barrier nothing is certain.

There's more, I should probably write a blog post instead of novels on HN


If I had a time machine, I would send this comment back to myself a few years ago. Would have saved me a lot of pain from “winging it”.

Thanks for sharing




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: