This is a common criticism but still extremely shallow. JPA/Hibernate is still the best way to actually produce working applications if you have to use an SQL database for some reason. To go point by point:
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.
Reflection (which is the reason classes must be non-final): again, sucks, again, the only way to do something like this in Java.
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.
Those who don't understand Hibernate caching are doomed to reinvent it poorly.
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.
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?
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.