> Mutable datastructures with default constructors and setters: yes, mutable entities suck. Unfortunately SQL is fundamentally built around mutable entities. Every field of your POJO is writable because every column of your database is writable. The impedance mismatch is big enough already without trying to make objects that behave differently from your database. Yes, an object shouldn't just be a datastructure with methods; unfortunately an SQL table row is just a datastructure, and classes are the only mechanism Java offers for representing such a thing. Same for mutable collections.

Every field is not writable in a database. There’s often constraints that restrict how fields can be updated. Requiring setters for all fields breaks that contract.

> Reflection (which is the reason classes must be non-final): again, sucks, again, the only way to do something like this in Java.

It’s the only way if you insist on having the entities track their own state changes via point in time snapshots. If they represent the changes themselves there’s no requirement for reflection.

> Lazy loading is wonderful. Put your session in your view, write a normalised set of entities that actually model your domain, and get on with your life. Don't worry about the details of what loads when unless and until you have to.

In the real world the lazy loaded view get tested with one widget loading five wozzles, then in production it’s one widget loading 5000 wozzles, each performing a separate query to hydrate its state.

> Those who don't understand Hibernate caching are doomed to reinvent it poorly.

Hibernate’s caching model manages to be both incredibly complex and incredibly limiting. Short of careful usage with an external store, it’s nearly impossible to scale across multiple JVMs. And even then it pushes the complexity to the cache.

> Don't use your database as an API. Yes, Hibernate/JPA needs to own your database. That's as it should be. SQL databases are way too complex to be shared between independent applications.

(Emphasis mine)

On the contrary, a well designed database can and will have many separate applications I retracting with it. All the more reason to have the database reflect the true constraints of the system.

> Do you really think people who can't be bothered to learn and understand Hibernate properly are somehow going to take the time to learn and understand "vanilla SQL"? Why?

The complexity of learning SQL is grossly overstated. Plus it translates as skill to all other languages and programming environments. On a purely economic basis it’s a better choice for an individual to learn SQL over Hiberate/JPA.

> None of the problems listed here are problems of JPA/Hibernate. They're problems of SQL databases which are surfaced through JPA/Hibernate, but if you skip out on JPA/Hibernate you still get exactly the same problems (maybe in a slightly less recognisable form). The real solution is to stop using these overrated datastores, but if you must use them then JPA/Hibernate is the least-bad way of doing so.

I think the ultimate example of how bad JPA can be is JPQL. They managed to take the worst aspects of everything, and then not just add them together, but multiply them!