5 ms·
Having managed myself multiple projects using various JPA implementations I think JPA is great for relational database driven applications. Some of my projects
by de6u99er 6y ago
Having 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...
- doctor_eval 6y agoPretty sure I would have used a list, but making the Java interface ordered surely doesn’t change the semantics of the underlying relation?!
- tablespoon 6y ago> Pretty sure I would have used a list, but making the Java interface ordered surely doesn’t change the semantics of the underlying relation?! Yeah, it seems a little bonkers on first glance and I haven't ever dug in to see if there was a justifiable reason or not. IIRC, if you just need ordering, you could just use an SortedSet. I think technically lists are for when you need ordering and duplicates.
- doctor_eval 6y agoYeah it is bonkers! Not just at first glance. The fact that the SQL integration for the child object behaves differently based on the kind of collection used in the parent is exactly the kind of unintuitive behaviour that drove me nuts. There are so many rules to remember for something that is supposed to make SQL integration natural.
- Ygg2 6y agoSets in Hibernate suffer because you can store an object before it was updated and Hibernate will update it. E.g. If say Person { id: Integer, name: String } Let's say I have some entity that stores Persons as HashSet. If I add them before saving, their hash set is taken without Id. Id can be automatically generated by Hibernate on save/create. After save the Id now has a new value. I.e. its hash differs from when it was saved. Boom. You have HashSet with Zombie entries. That are technically that you can't fetch actually.
- imtringued 6y agoHow do you get 75% fewer LOC without using JPA or Hibernate? All I have to do to create a new table is define a class with some attributes and the corresponding SQL migration, I don't even have to annotate anything. To create a new row I just do new Table(attr1: expression1, attr2: expression2).save() and I am done. Compare that to the usual mess of writing down the same column name four times with raw SQL (1. to reference the column, 2. to set the column value with a named parameter, 3. to set the named parameter, 4. declare the variable you wanted to save in the first place). Of course, I'm not using Hibernate directly, that would be foolish. Instead I am simply using Gorm to wrap the awful parts of Hibernate (the irony).
- doctor_eval 6y agoSo now you have code in Gorm generating DDL and JPA code? In terms of the compiled LOC, doesn’t this add even more code? Not to mention another dependency to maintain. Anyway - I’m definitely not advocating for raw JDBC, there are lots of libraries you can use to reduce the complexity of the integration with the database, it’s just that JPA is not (IMO) one of them. One thing I don’t understand about your comment it “the usual mess of writing down the column name four times with raw SQL” - when is this necessary? ’update table set column=? where key=?’ has no duplicate names. Can you give an example? I’m intrigued by how your solution to JPA’s verbosity problem is to add another layer, while mine is to remove one!
- overtomanu 6y agoI think he is talking about upsert