18 ms·
Problems with JPA/Hibernate
- karmakaze 6y agoHibernate was made to solve the problem of JavaEE enterprise bean persistence. It made sense 20 years ago. It is a mismatch for the API-oriented transactions we tend to write today.
- Areading314 6y agoWhat is the argument in favor of server-side Java in 2021? It seems like alternatives like Go, Python, or even JS are far ahead at this point
- the_af 6y agoFar ahead in what sense? In my previous job we used Java and the benefits were a huge ecosystem of libs and tools, plenty of monitoring tools, a ton of expertise and people who understood its memory model and quirks and were able to troubleshoot production problems. The JVM is rock solid and has great performance for backend with lots of transactions. I'm not experienced with Go, Python doesn't seem particularly suitable, and server-side javascript looks like a nightmare to me. NodeJS seems crippled to me.
- paulryanrogers 6y agoOne benefit I've been seeing with server side JS is from FAAS like Lamba which can serve unpredictable loads very inexpensively.
- eeperson 6y agoHow is that a benefit specific to JS? Don't those platforms generally support Java as well?
- cle 6y agoThey do but the Java ecosystem takes a hit here, with many libraries being slow to initialize. The slower it takes to startup, the longer it takes to absorb the new load, to the point where you either keep some headroom (IOW, waste $$$), or try to predict load (complex, also wastes $$$). There are attempts to fix this with e.g. Graal, which effectively does the expensive initialization and reflection at compile time, but there are so many downsides and pitfalls right now with Graal that I don't consider it a serious solution to the problem. It's basically creating a new ecosystem, which means one primary motivation--to take advantage of the Java ecosystem--is much less compelling. This isn't constrained to the public ecosystem, lots of companies have their own internal libraries, and Java makes it very easy and even encourages doing lots of expensive things at startup, like classpath scanning and pre-caching things. For a long time, Java made explicit decisions to de-prioritize startup time to improve maintainability (reflection/scanning/dynamic classloading) and runtime performance (e.g JIT). This tradeoff doesn't work out so well in a world of ephemeral processes that come and go as demand changes. I guess what's specific to JS, Go, Python, et al is the cultural emphasis on fast startup. Interestingly these all come from different constraints but the net result is that, in general, you can go from cold to serving traffic much faster than with Java, with a lot less effort.
- eeperson 6y ago> There are attempts to fix this with e.g. Graal, which effectively does the expensive initialization and reflection at compile time, but there are so many downsides and pitfalls right now with Graal that I don't consider it a serious solution to the problem. It's basically creating a new ecosystem, which means one primary motivation--to take advantage of the Java ecosystem--is much less compelling. I'm not sure I understand what the downsides are for Graal and FAAS. There are some pitfalls around reflection but even those don't seem to hard to avoid. Is that what you are referring to?
- alserio 6y agoNot gp but avoiding the reflection pitfalls is not so straightforward at all, you have to chase what your dependencies are doing to satisfy the "closed world" hypothesis. I still like java more than javascript, but writing performant serverless functions using js is way more easy right now
- AaronFriel 6y agoThe JVM is rock solid, and recent improvements in garbage collection have reduced tail latencies dramatically. But I find that most people who say that it has "great performance" have not built a parallel implementation in JS, Go, Rust, or even .NET Core. I'm omitting memory unsafe languages by default and Python here, because I think that's the domain Java competes in, and Python lacks the investment these other languages have in performance. The lack of value types and the amount of pointer chasing that JVM languages do as a result, the way generics are implemented via type erasure (which the JIT then has to re-optimize), and so on usually mean that CPU and memory usage for the same throughput is much higher than a competing implementation in a different language. And on older JVMs, tail latency will be orders - plural - of magnitude worse. It is absolutely true though that for most workloads that efficiency isn't necessary and the ability to reuse that ecosystem reduces time and cost to develop. But it's just definitely not true that Java has "great performance" and I don't think that's ever really been true.
- ssijak 6y agoTechEmpower Web Framework Benchmarks would like to disagree with you.
- AaronFriel 6y agoI don't think those are particularly realistic workloads, as they don't involve substantial amounts of working with in-memory data. Which of the TechEmpower benchmarks uses an ORM? Before I finished drafting my comment I did have a sentence like this, which I removed, "Barring obscene amounts of optimization", so yes, some web servers like netty and jetty have gotten to a level of good performance in terms of handling plain requests. But most line of business backends are not using plain jetty/netty, they aren't just responding to every request with the same "SELECT" query to a backend database. They're doing computation, they're storing intermediate data in data classes like ArrayList, TreeMap, etc. And then of course due to business requirements, they often have to implement some in-process caching, and suddenly the lightweight Java application is a bloated multi-gigabyte CPU consuming monster. I just don't see that happening often with more memory and cache friendly languages like Go, Rust, Swift, or even JavaScript on V8/Node.js.
- buster 6y agoA huge developer base and eco system? What specifically, can't be achieved in Java, that you think node is needed for?
- Scarbutt 6y agoRendering Javascript.
- SahAssar 6y agoThere is https://en.wikipedia.org/wiki/Rhino_(JavaScript_engine) https://en.wikipedia.org/wiki/Rhino_(JavaScript_engine) and https://en.wikipedia.org/wiki/GraalVM https://en.wikipedia.org/wiki/GraalVM. The latter of those is the second fastest js server runtime (es4x) according to techempower benchmarks: https://www.techempower.com/benchmarks/#section=data-r20&hw=ph&test=db&l=zik0sf-f https://www.techempower.com/benchmarks/#section=data-r20&hw=... I haven't tried any of those, but saying the JVM can't run JS is not true.
- rjsw 6y agoJava has support for the schema definitions that I need, the other languages you list don't. I am happily using JPA/Hibernate too.
- ssijak 6y agoWhat is the best argument against it? And the whole JVM platform in general (Kotlin, Scala, Clojure...)
- AzzieElbab 6y agoI can’t speak for others, but scala’s has two of the best sql db libs I ever used, namely doobie and quill. https://github.com/getquill/quill https://github.com/getquill/quill https://tpolecat.github.io/doobie/ https://tpolecat.github.io/doobie/
- rakoo 6y agoIt works ? I'll argue that 90% of problems solved by SaaS today could be solved by any of the usual suspects of languages. What matters more is the architecture you choose. Choice of language is mostly a convenience choice, based on how comfortable you will be editing software in that language (that includes not only your proficiency, but also the availability of libraries and frameworks to help you)
- deleted 6y ago[deleted]
- paulryanrogers 6y ago> This loop has to stop, what defines the value of the projects we are working on has nothing to do with technologies and frameworks. > I WANT to solve business problems, I do not want to keep solving technical issues. It is interesting how emotionally invested we become with our tools. Yet we don't have infinite time to become productive with all possible frameworks. So we have to specialize at least somewhat. As to JPA itself, I agree that it's generally a bad fit for most uses. Circa 2010 I used it with Java Enterprise in the hope that an failed bean could be recovered by a parallel worker, but the technical costs were crazy high. And often I had to drop to raw SQL anyway. Less invasive ORMs can still be more generally useful, and remove some tedium.
- vips7L 6y agoThis article is... Questionable at best. I don't think any of this is an argument against JPA, except that the author doesn't like how it works? I also suspect the author doesn't know hibernate that well. For instance selecting just the fields you need is relatively simple with JPQL: SELECT i.url FROM Image i WHERE i.id = ...
- nimchimpsky 6y agothat looks very like sql, whats the benefit then ? X amount of dependencies to write almost sql ?
- agilob 6y agoJPA and Hibernate make it very easy to use it incorrectly, its almost like they promote bad SQL queries and ideas. They let users of database connection to write Java-first database queries, when database query should be database first, it's just way too easy to abuse it and get too much data, too many columns and JOINs. Developers look like JSON looks like, what we send to browser, what formatting it has, validation and size of JSON data, as it's easy to monitor and trim. Can't say the same about Hibernate. How the hell even hibernate caching works? Why even are there 2 levels of Hibernate cache? It's too easy to create and abuse transactions. Dirty-checking is JUST WAYYYY TOOO EAZY TO ABUSE. not calling, using setter of an instance shouldn't update in database by default omg, It shouldn't be possible for transactions to leak outside some easily specified scope - I've seen one project where transaction leaked to Jackson!! Jackson was calling getters on fields and executing DB queries. JSON ended up as 2.6Mb instead list of 10 fields. Hibernate is popular because we don't need to learn SQL to get needed data, but it's also super hard to get it right and don't do something stupid by accident. If in any doubt, refer to JOOQ - it's the SQL-oriented ORM for Java.
- vips7L 6y ago> How the hell even hibernate caching works? Why even are there 2 levels of Hibernate cache? https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#caching https://docs.jboss.org/hibernate/stable/orm/userguide/html_s... > using setter of an instance shouldn't update in database by default omg This doesn't happen.. the database won't update until you ask the entity manager to persist the entity. > I've seen one project where transaction leaked to Jackson!! Jackson was calling getters on fields and executing DB queries. JSON ended up as 2.6Mb instead list of 10 fields. I suspect you might not agree, but JPA lazy loading is one of the easiest concepts to understand. However, I'd argue that leaking your database models to the view is a mistake to begin with and said application is already incorrect. > If in any doubt, refer to JOOQ - it's the SQL-oriented ORM for Java. Both the author/maintainer of jOOq and Hibernate agree that each has their place. I really am amazed at developers that don't take the time to learn about the tools they use.
- the_af 6y agoThe underlying problem is one of O-R impedance mismatch. Going full SQL and getting rid of the ORM is a possible answer, but it has tradeoffs and is not a silver bullet. It might mean re-creating from scratch an in-house, bug-ridden ORM, or ditching OOP idioms from your language, or both. The author of TFA seems to be going through one of the stages described in "ORM is the Vietnam of Computer Science", an article that should be mandatory reading before one claims to know the solution to this decades old problem.
- phreack 6y agoHere's the article http://blogs.tedneward.com/post/the-vietnam-of-computer-science/ http://blogs.tedneward.com/post/the-vietnam-of-computer-scie... Edit: huh, seems to have got truncated over the years. Here's an archive link https://web.archive.org/web/20160120004603/https://blogs.tedneward.com/post/the-vietnam-of-computer-science/ https://web.archive.org/web/20160120004603/https://blogs.ted...
- hagy 6y agoI've found jOOQ to provide the right tradeoffs and flexibilities for ORM vs. SQL. First, it can generate object models of tables from the database in development and therefore doesn't rely on any specific migration tool. These model classes can be used in a conventional ORM fashion, but you also have the option to use jOOQ to build SQL queries. You can even fetch the results of arbitrary SQL expressions into a model class, which can handle partial population of columns. This allows combining ORM and SQL approaches with some code operating on models where that is natural, but this code can be applied to models which are fetched in alternative fashions when that is more preformat. E.g., fetching records using criteria that involves joins and only selecting relevant columns for the subsequent processing of fetched results. The jOOQ "DSL" (i.e., Java interfaces and static methods) gives you essentially the full power of SQL without having to rely on external SQL files or stored procedures. (Or even worse strings.) You can even programmatically build these queries. E.g., optionally including different WHERE/HAVING criteria. The jOOQ "DSL" provides a fair amount of compile-time type safety, which isn't possible with external SQL.
- 6y ago
- api 6y agoFrom my experience ORMs are good time savers when you have relatively simple query needs, but fall down when things get really complex.
- Daishiman 6y ago"Really complex" means getting down to 6 or 7 joins for your typical SQLAlchemy or Django ORM query. These sorts of queries comprise 5% of my queries, tops. Seems like a fair tradeoff.
- tarkin2 6y agoI have one of those queries. It's the most important in the database sadly. As django bloats and bloats the table space, over the years, more and more do I need those queries, and slower and slower becomes my app.
- Daishiman 6y agoThe mapping of Django models to tables is trivial. Django's not introducing a difficulty, though the entity modeling may be.
- dopidopHN 6y agoExactly, with hibernate if something is too hairy, I use the native query system. ( and hibernate still map the result for me )
- The_rationalist 6y agoNothing prevents you from using raw SQL queries with Hibernate. HQL is just a convenient superset.
- nimchimpsky 6y agowhats the advantage of that ?
- karmakaze 6y ago
- jacques_chester 6y agoI largely agree that JPA is a maddening mess[0]. However, this sentence caught my eye: > I love open source, really, but big companies sponsoring open-source projects get most of their income from support or third party tools. I work for VMware and consequently take some interest as to how my salary comes into being. If you think VMware makes "most of its income" from supporting Spring, then I think I'd encourage you to spend some time at the investor relations site[0] reading any of the annual or quarterly reports. I'd advise the same for Oracle and Red Hat/IBM. [0] The advice to use emails or SSNs as primary keys, though: yikes. [1] https://ir.vmware.com/ https://ir.vmware.com/
- lmm 6y ago> If you think VMware makes "most of its income" from supporting Spring, then I think I'd encourage you to spend some time at the investor relations site[0] reading any of the annual or quarterly reports. VMware is a huge company with its fingers in many pies, but I suspect if you rewrite the sentence as "most of their income attributable to that open-source project" then it would be true of such companies. Presumably VMware sees a return on investment for its sponsorship of Spring (otherwise why do it?); if that's not coming via support or non-free tools that build on Spring then where is it coming from?
- jacques_chester 6y agoI can't speak for folks moving in VMware's most exalted circles, but from my personal perspective the aura and reflected glamour are valuable in itself. Spring's reach and influence in enterprise programming is enormous. Put another way: I don't think Spring makes money. It makes making money easier.
- dale_glass 6y agoI disagree with this bit: A User can be considered unique in one context by its email address, or by its social security number Personally, I'm a fan of giving everything a random UUID, because it's more flexible. It's random and impossible to guess, it scales well because there's no central bottleneck like with an autoincrement, and it's future proof and flexible. What happens when the user changes the email address? What if the social security number changes, because it was wrong or because it actually changes? What if the original unique identifier wasn't a good choice? What if we decide that the user can have multiple email addresses? Then you may end up having to restructure the entire database, which will be a very annoying thing to do. What if you implement additional rules for what an email is allowed to look like and now the constraint fails for existing users, and this correction needs to be propagated to millions of already existing rows? Real-life personal data is weird and fuzzy. They can violate seemingly sensible rules like being unique, unchanging, or conforming to any rule whatsoever. Best not to let them spread all over the DB and cause trouble later. Instead, you could just have a random ID that doesn't mean anything and therefore can stay fixed forever, and any user-related metadata stays in the user table, where it can be modified as needed. Plus an UUID is a fixed 16 bytes, which is easy and efficient to deal with.
- jacques_chester 6y ago> What if the social security number changes, because it was wrong or because it actually changes? What if the user doesn't have an SSN? What happens if they have one but lawfully refuse to provide it? What happens when you ask for and SSN from a US citizen who is also a European citizen? What happens when your database leaks? In general, relying only on natural keys is a nightmare. Double nightmare if it's PII. Natural keys only work if you are flawlessly omniscient about the domain. And you aren't.
- echelon 6y agoI want to print this comment and frame it.
- haspok 6y agoHow do you look for a person, if not based on his/her SSN? SSN alone is not sufficient, of course. But it _is_ definitely part of the natural key that you use _implicitly_ ANYWAY, whether recognizing it or not. > Natural keys only work if you are flawlessly omniscient about the domain I would call that BS. Nobody is "flawlessly omniscient" about anything, not even in mathematics, yet we design and build systems that work. On the other hand, yes, it is a very good requirement to have someone on the team during database modeling who understands the domain model thoroughly. No UUID columns will save you from that.
- victor106 6y agoJust because you're using Hibernate doesn't mean you have to use it for everything —Gavin King, creator of Hibernate Source:- https://twitter.com/markuswinand/status/456827165938434048?s=21 https://twitter.com/markuswinand/status/456827165938434048?s...
- alserio 6y ago"But then say goodbye to the consistency of your second level cache" - Gavin King, probably
- harryvederci 6y agoThe only positive experience I've had with it was in a small application with a not-so-complex DB which was created entirely through Liquibase. In large enterprise projects, I've always had to create custom SQL statements at some point, at which point I'd rather do everything in SQL. Otherwise, you have to know JPA/Hibernate and SQL, which (in my opinion) defeats the purpose.
- doctor_eval 6y agoIn my extensive experience managing teams using JPA ORMs including Hibernate and EclipseLink, you not only get to learn the unavoidable details of your target database’s SQL, but also the complex, non-obvious side effects - especially caching interactions and performance edge cases - of the ORM as well. You also get to learn two distinct but similar query languages (one of which you can’t use anywhere else but Java). You get to throw away all the semantics built into the database structure, including knowledge about indexes, and you need to duplicate almost everything from SQL into Java, in the form of complex annotations against entity objects that you often wouldn’t need with traditional SQL access patterns. And when something goes wrong, you have a large, complex framework, including an inscrutable caching layer, between your code and your data - which can make debugging JPA code very challenging. In return you get reduced performance, overly complex and difficult to read SQL code generation, an inflexible entity model, and non optimal database access patterns. JPA is an extremely complex framework whose benefits, in my opinion, outweigh the costs in only a small number of relatively simple use cases. And even in those simple use cases, in my experience it is far less performant (and double the LOC) than using SQL directly. I’m not saying you can’t use JPA in large, complex applications, because you obviously can. But those applications are harder to write, much larger, less maintainable and less performant than the equivalent applications written with simpler frameworks or libraries. I personally found MyBatis annotated interfaces to be the ideal way to map SQL to Java, but perhaps ApacheDB is better for smaller projects. JPA is one of those fabulous engineering experiments that, sadly, didn’t work out. It breaks every rule in the engineering book in order to make SQL work like Java, but it doesn’t succeed, and I could never recommend it to anyone.
- wrwatson 6y agoI am called apon to investigate database performance problems. Teams using Hibernate sometimes send me the Hibernate query. This is not enough to understand the SQL which has been issued. I would also need to see all the entity objects, and maybe some configuration parameters. Without the SQL, which nobody can exactly predict, it is difficult to performance tune. So they turn on logging, get the SQL, and email that unreadable mess. In most of the cases I have seen, the SQL is fetching much more from the database than what the code really needs. The first step when optimising SQL is to only ask for data that you actually need. Hibernate, as I have seen it used, defaults to fetching too many columns. I cut the SQL down, and come up with a performant statement. The developer has the challenge of translating the performant SQL back into Hibernate. Hibernate makes easy things easier and harder things harder.
- kleinsch 6y agoEveryone hates JPA/Hibernate, but what’s the alternative? I’ve seen this a few times. “You don’t need an ORM, write your own SQL queries directly and create a beautiful domain driven design object model” leads straight into a project only the owner will understand. Homegrown mini-ORM that’s full of pitfalls, inconsistent object model, hacks and TODOs all over the place. If you’re living in the Java ecosystem, the biggest benefit is that you have a massive library ecosystem and developer base that understands it. If you’re going to throw all that out and require new people to learn your homegrown mess, why not pick a language that’s more interesting than Java? Then you’ll get new developers that are anxious about Go/Elixir/WhateverHotness. Saying this as someone with 15 years in Java world.
- stuff4ben 6y agoExactly! And can you even call yourself an experienced Java developer if you haven't written your own ORM at some point?
- dopidopHN 6y agoGosh has it been 15 years already? I never liked Java much. But several companies I liked and hired me where using mostly that. Then I did some consulting / freelancing / firefighting. ORM and mostly Hibernate was often a topic. My experience and methodology is as follow : - Write test for your ORM layer. Possibly not in Java. Some high level integration type test. ( calling your web-layer or API and checking for what comes out ) - Burn your ORM layer down. - Have someone who know the business logic sit with you. And re-write the ORM layer from mostly scratch. - While doing the above, train that person on the very redondant gotcha ( Inverse n to n, accidental carthesian product, bad ID generation, compulsive flush, un-needed @lazy or @eager to deal with performance, @embedded abuse and fucked up SQL schema because of the previous) - Train all dev on the persistence lifecycle of stuff in JPA. "No, most likely you won't have to call .persist or .merge yourself" being the bottomline - Have a shiny documented exemple of 1 to 1, N to 1, N to N examples ( both with or without inverse link ) - If some report or API needs a fucked up SQL query with 18 join. Write that thing in native SQL and shove it in your DAO. You don't need to mess up you'r whole DAO layer for those 3 queries - Pray - Run the test from step 1. --- TL;DR : if the ORM layer is somewhat clean. you can mostly forget about it. On the project I'm on now, I did not had to touch it more than once in 2 years. ( and that was terrible, granted, we touched a test and stuff that had nothing to do with it started to blow up. But still, once in 2 years is not a lot )
- KamBha 6y agoI find this argument a little odd:- "Frameworks do not keep retro-compatibility" I would argue that is a good thing and in the case of Spring, doesn't feel true. In part, Spring is so hard to learn because it has too much support for legacy stuff (though this may have changed in the last few years). The only issue with not supporting retro-compatibility is because the JVM doesn't support retro compatibility. I recently tried to upgrade an application to the latest version of Java (I think it was Java 12) and found that date formaters were completely changed to match an ISO standard which broke a lot of code. We also found a similar problem with the Java 8 transition as well forcing a huge upgrades to our libraries. I am of the view that libraries and frameworks should support not support retro compatibility but the language should. This way, if you don't want to upgrade your library then you don't have to. Using the web as an example, old Angular JS applications still work today as they did back when they were first written. I doubt applications written in the first version of Spring will work with the latest version of the JVM.
- lmm 6y agoThis 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.
- manyxcxi 6y agoI disagree on most of your points but I am trying to read your entire comment favorably, but my personal experiences do not line up with almost any of this. >>> JPA/Hibernate is still the best way to actually produce working applications if you have to use an SQL database for some reason... This statement makes me think that you either do not prefer to use SQL RDBMS, don’t have to use them very often, believe they are some dusty piece of tech, or all of the above when my experience has me believing that RDBMS are absolutely the most common persistence layer I encounter in JVM, .NET, PHP, and Python codebases. I don’t think I’ve ever heard a senior JVM based engineer proclaim that JPA/Hibernate are “the best way... to produce working applications”. It simply isn’t. For basic CRUD applications you will AT BEST barely write fewer lines of code with JPA than with native JDBC queries and ResultSet mapping and have all the lock-in and performance drawbacks of JPA. Lazy loading will inevitably wind up with Session scope problems with any kind of concurrency, forcing nasty internal list enumeration to force a faux eager fetch to work around the problems. Fetching just the columns you need for a particular projection will have you writing either SQL or Hibernate “SQL” in annotations. If you have a mix of JDBC and JPA in a codebase you will inevitably wind up with enough consistency and visibility issues as to either ditch one of them or ditch the entire codebase. Vanilla SQL is so pervasive and CRUD operations are so simple that I would have serious doubts about the credibility of a JPA proselytizer that didn’t know SQL. I expect every single one of my backend engineers (on any tech stack) to understand the fundamentals of SQL INSERT, UPDATE, and DELETE statements.
- xupybd 6y agoI have been using Entity Framework recently. I've not had any past experience where I have liked an ORM. This one seems alright. I do wonder if I will fall into the same trap as complexity grows. But the migrations are just amazing so far. For them alone I want to stick with it.
- exabrial 6y agoI don't want to sound like I particularly love the orm pattern when I say this... But his information is about 10 years out of date. Many of the claims simply aren't true anymore or the world has moved past by other means. For instance one of his very specific claims, getters setters must be present, definitely is not true for current versions of every JPA implementation. In the claim about a default noop constructor, you can't possibly be serious unless you are doing true oop and in that case you are awarded no points and may god have mercy on your soul. The beauty of dependency injection is it did more to make Java a functional language than Java8 with lambda notations. That pretty much eliminates the need for pure OOP, which JPA attempts to imitate. In reality JPA + JTA is a pretty awesome combination and avoids the stupid OOP paradigm. Again. Argh. I would write a response blogpost, but argh, apathy for the orm pattern.
- victor106 6y agoLot of Hibernate hate in this thread. This really helped me. Strongly suggest. Also Vlad writes really awesome posts on using Hibernate along with Spring etc., https://vladmihalcea.com/courses/ https://vladmihalcea.com/courses/
- alserio 6y agoVlad Mihalcea is awesome! However, Hibernate, while helping in some use cases, in my opinion should not be the default solution one reaches for. It makes way too easy to do things in a way that works for a while and explodes later. And it is way too easy to be misunderstood, leading to performance and compositionality horrors. Still it is the only Java solution I know that manages to be reasonably portable between different DBMS.
- Uehreka 6y agoSorry for being off-topic, but why is Hibernate called Hibernate? I can't find an explanation on the Wikipedia or GitHub pages, and whenever I see the name come up on HN my brain does a weird double-take as it goes "Is this an OS hibernation tool--No, it's the Java database thing... does it make objects go to sleep?"
- nwatson 6y agoProbably a reference to how JPA-Hibernate lets you fatten up your creatures (in memory) and then put them to sleep (in the RDBMS) until they're ready to play again.
- dirkt 6y agoYes, it makes your objects go to sleep. The use case is "you have a collection of objects that reference each other in memory. You want to say: Bam, put that structure like it is into a database ("put it to sleep"), and retrieve it again for me if I need it ("wake it up after winter is gone")." For this type of ORM Hibernate works fine. If you want to use a database as a database, it resists at every turn.
- jillesvangurp 6y agoThere are lots of valid reasons to avoid JPA/Hibernate beyond those listed in the article. - Hibernate is using blocking IO and threaded database pools. This makes it a problem if you want to use non blocking web frameworks. Like Spring's web flux. You should consider it a legacy technology for this reason alone. There's a good reason why there is no drop in reactive replacement: modern frameworks are trying to not repeat some of the design problems with hibernate (see the article for an overview of those). - It comes with its own category of hard to diagnose and fix bugs. I've been on more than one project where I had to clean up other people's messy transactional logic. One symptom is people copy pasting @Transactional everywhere as if it was some kind of magical incantation that says "dear db gods please just make this work consistently". A second symbol is flaky tests where that clearly is not working as advertised. A lot of this relates to things like aspect oriented programming and reflection which are what hibernate uses to generate byte code at run time. - For the same reason, hibernate is also a problem if you want to natively compile your code via e.g. Graal. Reflection and byte code generation are problematic for that. The less you have of that, the better. - For the same reason, hibernate is also inappropriate if you need fast startup times (which would be why you'd consider native compilation). For example because you are doing server-less designs or edge computing. Having 10-15 seconds of startup overhead is not great. Warming strategies can mitigate this somewhat. But honestly, there's no good reason for Java servers to take much longer to start than it takes the JVM to start (which is still around a second or so). As soon as you get rid of hibernate, Spring Boot startup times become a lot more reasonable. If you then switch to using it's bean DSL (as opposed to scanning packages for annotations), it gets better still. Most of what Spring does at startup is millions (literally) of calls into various reflective methods. That's why it takes so long. - Object impedance mismatch. Designs that need an ORM layer might not be that optimal. I've been on multiple teams where people got carried away a little too much with e.g. overusing inheritance and coming up with complex solutions to make the database mirror the class hierarchy. The result is dozens of tables and dozens of joins on read. I've seen GET operations that had 1500ms response times because of this. It's stupid. It's stupid even after you fix all the silly joins, missing database indices, etc. You can do good database design with hibernate of course. If you understand how to do that, hibernate is just another tool and not a particularly critical or important one. I've removed it on a few projects to simplify the design. - These days it is valid to treat databases as document stores. Once you refactor a 15 table database to be the 3 tables that you really needed all along, most of Hibernate is just not needed. My golden rule is that if I don't query on it, I don't need (or want) separate tables or columns for it. Nothing wrong with storing some json blobs. I love using databases because they are fast, transactional, and come with some strong consistency guarantees. Hibernate is not a great fit for document databases. It assumes your domain consists of columns and tables and it wants to do clever things with joins to make that seem like an object tree. The best join is the one you don't need. That's why document stores can be so nice. If I had to do a green field project, I'd probably go for R2DBC with Spring or maybe one of several other Kotlin reactive database frameworks in combination with ktor, http4k or one of the other emerging Kotlin server frameworks. All my recent projects are using spring web flux and Kotlin co-routines in any case. So, using something non blocking is a hard requirement for me. But if I had to use hibernate, using Kotlin is the way to do it. It shovels most of the ugliness under the carpet via compiler plugins. So you can use nice immutable data classes and let the kotlin compiler worry about adding default constructors, opening the class and adding getter and setter cruft just so hibernate can do its runtime magic. Also it removes all of the need for hacky things like Lombok and its gazillions of additional annotations. Hibernate can be a lot less painful if you just do it properly. But not using it is better still.
- amenghra 6y agoI solve Hibernate problems by using jOOQ instead. The migration more than paid off the couple times I did it.
- ChrisWreck 6y agoHow do you solve storing/updating/removing child entities of another entity (which also may be a child of another entity) effectively? I use jOOQ as well, but mostly only for the reading part. For the above case, I still use Hibernate, as I've yet to find an efficient way to do it in jOOQ.
- cryptos 6y agoEven Lukas Eder, the creator of JOOQ, suggests to use Hibernate for CRUD and JOOQ for querying: https://blog.jooq.org/2015/03/24/jooq-vs-hibernate-when-to-choose-which/ https://blog.jooq.org/2015/03/24/jooq-vs-hibernate-when-to-c...
- amenghra 6y agoMy models have always been fairly simple with not too many levels of child entities. I contain all the logic for a given entity in a single class (where I hand write the code to update related entities). I do have to keep my fingers crossed that nobody will implement similar-but-wrong logic in some other spot in the codebase. The 1:1 mapping between entities and classes to CRUD helps to some degree.
- kgeist 6y agoInteresting, as far as I know, PHP's Doctrine was influenced by Hibernate but it doesn't require parameterless constructors, and data is hydrated directly as object fields, without requiring getters/setters. What's the reason for enforcing such requirements in Hibernate?
- watwut 6y agoIt is JPA requirement. In java, if you are creating new object, you have to call some constructor. If you dont have no parameter constructor, the framework would have to somehow call a constructor with right paramaters. The date are filled directly to fields. But no parameter constructor is needed so that object can be created in the first place. Now, in Hibernate itself, the no-parameter constructor is not needed. Hibernate supports an "interception mechanism" which allows you to use whatever constructor you like. But that is not part of JPA standards and for most it is simpler to just go standard way.
- nnanda 6y agoJPA madness is still ON and that is unfortunate. Spring framework guys at Pivotal are designing all kinds of database access (SQL, NoSQL) around JPA interfaces.
- watwut 6y ago> Nobody understands the cache mechanism, you end up de-activating it. Worse, those understanding it are not caching query responses, they are caching entities. I feel like hiring process should filter these kind of developers out. At least most of them. I also think that if they get in, internal processes should limit these developers impact, limit their ability to make decisions. As in their careers should be stagnant and they should not be gaining influence.
- ChrisWreck 6y agoGoing from using only JPA/Hibernate for everything, to use a combination of both jOOQ and JPA/Hibernate on a project, is probably the best decision I've made. Using each tool at what I believe they do best. I use JPA/Hibernate for most writing and inserts. It helps a lot when you're dealing with aggregates with child and child entities. It would be a nightmare to track all changes myself and try do manually do what the ORM is doing for me. Deleted a child of a child of an aggregate? No problem, persist only that. I've started to separate my JPA/Hibernate entities from my domain models as well, and it looks promising. There's some more mappins, but my domain won't be polluted with database concerns. Then I use jOOQ for almost all reading of data, reading into custom read models that fit the view they are supposed to be shown in. No problem doing multiple joins or other stuff that would give you an immediate headache when trying to solve using JPA/Hibernate.
- islon 6y agoThis post reminds me of what happened some weeks ago at my job. We use Clojure and yesql (a library where you write sql queries directly in .sql files and the library generates functions for you). The devops noticed one of our queries was slow and taking too much DB resources. He sent us the query which we promptly found and then asked us if we could change it to a more performant version he just wrote. We took his query, just replaced in our sql file and deployed. 10 minutes later he came back saying things look much better and the query update really helped. I wonder how much time it would take if we were using JPA/Hibernate as we used to, many years ago.
- cryptos 6y agoA default constructor must be present, yes, but if you use Kotlin a compiler plugin can generate this constructor that is not visible in your code base (but would be if another module would use the compiled byte code). JPA/Hibernate does not require getters and setters. Fields can be used directly for ages (more than 10 years). The arguments against reflection are pseudo arguments, because the developer doesn't use reflection himself where usual programming language means would be better. Instead the framework uses reflection to free the developer from writing boilerplate code - completely different things! The claim that it would be impossible to return unmodified collections because one would be forced to provider getters and setters is wrong. If Hibernate uses the fields directly, it is no problem to give only an unmodifiable view of a collection to the outside. I don't see a general problem with lazy loading. You have to understand what you're doing, but that should be the case with every framework. Hibernate is quite flexible with eager and lazy loading and it is possible to specify an entity graph per use case to say Hibernate what to load eagerly and what not. Another possible is to use dedicated query objects (usual entity classes mapped to the same table, but designed for a certain use case). The section about "Accessing a single table field" ignores the fact that the object mapped with Hibernate could also only use the needed fields. You could even select a single value with JPQL without any domain class involved. This argument is kind of dumb and wrong. "Constraints" with Bean Validation are not a core part of Hibernate and shouldn't really be in this article. But, as they are already there, let me say that the criticized "too late" enforcement of the specified constraints is only the default behavior (because Hibernate can not know when to perform the check). Nothing prevents you from performing these checks explicitly with the means of the Bean Validation API. But apart from that, I'd prefer to write this kind of rules as usual code, too. "Framework updates are horrible": I had never a severe problem switching to a new Hibernate version. Same is true for Spring (but wait, why does this article mention Spring at all?). "Rename your JPA Repositories to JPA DAOs": The author doesn't understand the difference between a DAO and a Repository. A repository is at the same level as an entity or value object, it _is_ a domain concept. BUT the implementation of the repository interface is indeed part of the infrastructure, but this implementation would reside in another package. There is no need to name "repositories" always "repository" - if you want to name the class "BankAccounts" then do so! By the way: the class name "BankAccountsJPAImpl" is a crime! The advice to generate IDs in your own implementation is kind of silly. "if an id is generated, it should be done knowingly" Why? Usually an ID is just a number with no special meaning other than being unique per entity type. Even if you'd decide to drop relational databases and use advanced CSV files instead the sequence number generation could easily be implemented then. And why on earth should one want to test the sequence number generation? I trust every solid database to be able to generate perfectly fine sequence numbers! The section "Stop adding multi-directional association" has nothing to do with Hibernate specifically, because that is some kind of general design consideration. One big question remains unanswered by this article: What is the alternative? The author implicitly suggests that it would be SQL. But things are not so simple. If you want to have a domain model (and not a mixture of domain logic and technical infrastructure), you not only have to load data from the database and create objects from it (the easy part), but you also need to find out what data needs to be written to the database after business operations were performed. I'm not aware of a simple solution here (but let me know ...). There are other things like optimistic locking where Hibernate simplifies things a lot. All in all the article is not well balanced and flawed.