5 ms·
In my extensive experience managing teams using JPA ORMs including Hibernate and EclipseLink, you not only get to learn the unavoidable details of your target d
by doctor_eval 6y ago
In 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.
- doctor_eval 6y agoMeh, I think JPA makes easy things expensive and hard things really hard. :)
- cletus 6y agoMan, you and I see eye to eye here. I'm a firm believer in leaky abstractions [1]. I often found with JPA that I would be fighting the framework to get it to produce the SQL that I wanted. I encountered (then) ibatis and it was a breath of fresh air. It took care of much of the tedious column-to-Java mapping and didn't introduce another DSL. As soon as anyone tells you "you don't need to learn X with our framework Y that sits on top of it", all that means is you have to learn X, Y and the X->Y and Y->X translations and all but the first is proprietary. This was my core issue with GWT (Google Web Toolkit) too. Too many engineers who weren't interested in learning Javascript saw it as a way of avoiding learning Javascript. It's been many years at this point since I've used it so this may have changed but I recall that query verification was a runtime error issue and there wasn't a good way to essentially check that all your queries were valid. I mean you could write this yourself but it seems like some CI/automation could've done a lot of the heavy-lifting. IIRC the same went for integration testing and stub databases for reading and writing via ibatis/mybatis. [1]: https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/ https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-a...
- doctor_eval 6y agoI love the analogy to GWT and suffered it first hand - we believed the hype, that we didn’t need to learn JavaScript - but in the end we ended up needing to fully understand the whole stack in order to work through edge cases. I don’t mind leaky abstractions but the killer with JPA was the cache. IIRC, mixing pure SQL with JPA was really tricky because you’d end up with cache inconsistencies. So the JPA abstraction was leaky but the the framework effectively assumed that it wasn’t, which lead to all kinds for workarounds.
- js8 6y ago> As soon as anyone tells you "you don't need to learn X with our framework Y that sits on top of it", all that means is you have to learn X, Y and the X->Y and Y->X translations and all but the first is proprietary. Exactly, except it's not just about language Y being proprietary. (I am using term "language" instead of "framework", because they are, in the broad sense, conceptual languages.) It gives you a hint when the language Y is worth having in addition to language X - only if the language Y makes it significantly easier to model problem in your domain. Therefore, by definition, the language Y has to have some limitations that X doesn't. If Y is as a general language as X is (it can express same problems with similar effort), you end up doing busywork translating between X and Y. And this problem plagues ORM frameworks of all sorts - it's not clear what is more easily expressed in the language of the ORM, which is not already expressed in the relational algebra (and SQL), and conversely, what are you giving up by using ORM. Although it happens in all sorts of DSLs.
- de6u99er 6y agoHaving managed myself multiple projects using various JPA implementations I think JPA is great for relational database driven applications. Some of my projects contained 150+ tables. I always use a combination of JPA and JDBC. And everything derived from a base object that comes with create and update timestamps and users, plus a uuid based id field. The trick is that while knowing what you are doing in regards of limitations and performance, you design the data model alongside cardinalities from user facing components. You'll end up with a highly normalized schema. The nice thing is that you can create views later on and transform data into shapes that are more useful to others. If you make the mistake to start with the data-model only without knowing how the data is being collected or used you will most likely spend lot's of time converting entity objects into other objects and the other way around. The worst thing I have seen in my career, was half of the business logic implemented in Java and the other half in PL-SQL. JPA is great for large projects! I haven't had a single issue that we could not solve.
- doctor_eval 6y agoJPA is OK (but only OK) if you don’t have anything other than JPA accessing the database but in our largest application (1,000+ tables) this was never going to be the case. We had plenty of experience with database design, that’s not the problem. But we found even in simple applications with a dozen tables, the generated SQL was suboptimal. For example, to delete the children of a parent row resulted in a DELETE statement for each child row. I’m sure there are loads of good reasons why it did that, but it’a not something that you’d even consider in pure SQL. The systems I build these days tend to put 100% of the database logic in the database using (you guessed it) plPGSQL, and leave Java (or actually Go these days) to do the non database transforms, networking etc. you could say that I replaced learning about JPA with learning more about the insane capabilities of my database. I’m sure you (and half of HN) are gagging right now, but I know I’m not alone, and I’ll take 75% fewer LOC and 1-2 orders of magnitude performance improvement over JPA any day.
- tablespoon 6y ago> But we found even in simple applications with a dozen tables, the generated SQL was suboptimal. For example, to delete the children of a parent row resulted in a DELETE statement for each child row. I’m sure there are loads of good reasons why it did that, but it’a not something that you’d even consider in pure SQL. IIRC, it does that if you use Lists instead of Sets. https://dzone.com/articles/best-performance-practices-for-hibernate-5-and-spr https://dzone.com/articles/best-performance-practices-for-hi...
- debarshri 6y agoHave you ever tried - ormlite-core[1]? I recently found this obscure but quite stable library, kind of fell in love with it. [1] https://github.com/j256/ormlite-core https://github.com/j256/ormlite-core
- edem 6y agoThis comment is spot on. JPA/Hibernate is a very big leaky abstraction. That's why I ditched the whole thing and started to use things like jOOQ instead. In the end you must learn SQL to make sense of all of this anyway.
- eitland 6y agoGenerally you should use the right tool for the job and that might be something else. This however: > You get to throw away all the semantics built into the database structure, including knowledge about indexes, suggests you either don't know JPA very well or your writing is a bit sloppy. Please avoid making sweeping generalisations about tools that save hundreds (or al lot more) of hours of programmer tools just because you didn't get it. Too often I see people going with a lesser alternative because such comments are scaring them away.
- sabellito 6y agoThey made some concrete criticism based on their experience (hard to maintain, complex annotations, etc), but you in turn dismissed those with "you didn't get" and some borderline name-calling. Which bit they didn't get?
- eitland 6y agodoctor_eval wrote: >> You get to throw away all the semantics built into the database structure, including knowledge about indexes, I wrote: > suggests you either don't know JPA very well or your writing is a bit sloppy. To suggest that JPA means "throw[ing] away all the semantics built into the database structure, including knowledge about indexes" indicates either that the person doesn't know what JPA is about: indexes should be used with JPA for all but the most trivial setups. Same goes for other general database knowledge. You wrote: > They made some concrete criticism based on their experience (hard to maintain, complex annotations, etc), I just pointed out that it was either a misunderstanding or so sloppily written as to create misunderstandings. > but you in turn dismissed those with "you didn't get" and some borderline name-calling. Which bit they didn't get? The bit about JPA not standing in the way of using good database practices. It is not name-calling. I point to the exact words doctor_eval uses. To be polite and also be sure to make room for error on my side I also offer the option of sloppy writing. Sloppy writing happens to all of us and I'll be happy to know if doctor_eval didn't mean it or if I've misread it. If not however it is not smart to use big words to try to trash a super useful tool that save many of us lots of time and often increase quality.
- kimi 6y ago"Bad practice - if you hide the database, you may get something done quickly, but it's a bad idea. If your Java code expects to have a collection of one million objects as an array, it does not matter if they are lazily loaded or not - some code somewhere might want to iterate over them, and this will kill the process. You cannot really forget that there is a database somewhere, and you should not do it." https://github.com/l3nz/ObjectiveSync https://github.com/l3nz/ObjectiveSync
- doctor_eval 6y agoGreat synopsis of JPA problems generally!