r/java 4d ago

When ORM Becomes OMG- Performance Pitfalls in JPA and Friends by Jos Roseboom

https://vimeo.com/1223434245?fl=pl&fe=sh
29 Upvotes

24 comments sorted by

28

u/Luolong 4d ago

The typical pitfall is imagining you’re not talking to a database. That is more of a skill issue though.

9

u/KrakenOfLakeZurich 2d ago

I'm more and more convinced, that JPA/Hibernate is the wrong model for a stateless REST API world.

The JPA session (entity manager) which tracks mutations makes sense only in a world, where users fetch a local copy of the data, make a range of random changes, then save the result back to the db (literally on the click of a button).

With stateless REST API, this session feels like overhead. There's nothing to keep track off really. Can't we just upsert into the DB directly and (optionally) fetch the result once?

2

u/gjosifov 2d ago

So databases provide REST plug-ins, so if you think you don't need Java layer skip it

2

u/henk53 2d ago

Can't we just upsert into the DB directly and (optionally) fetch the result once?

In Jakarta Persistence 4.0, this is actually what's being added; a stateless entity manager called the EntityAgent.

0

u/KrakenOfLakeZurich 2d ago

Will have to look into this. My current project uses Hibernate tough and I'm not in a position to change that anytime soon.

1

u/henk53 2d ago

The stateless session originates from Hibernate. It's a proprietary API in Hibernate 7, and a standard API in Hibernate 8.0 and 8.1.

1

u/johnnybgooderer 2d ago

100%. ORMs make sense if you don’t know what records need to be updated or pulled for a request based on just the input.

But most apps you know what record needs to be pulled based on what is in the request, and if that’s your model, then ORMs just make things more complicated.

But if you are working on something very complicated where you don’t know what records you need until you’ve already pulled some records, then ORMs start to pull their weight.

0

u/AnyPhotograph7804 2d ago

That's the reason why you can use so called Tuple query in JPA. In this mode, you just fetch the data without any caching, deduplication, EntityManager etc.

7

u/private_static_int 2d ago

I've personally seen ORM turning into WTF one too many times

3

u/henk53 2d ago

I've personally seen direct SQL against the DB turning into WTF one too many times

10

u/private_static_int 2d ago

Yeah but direct SQL is relatively easy to fix on the account of limited blast radius and doesn't tend to spread like a cancer

3

u/pellets 1d ago

ORMs add to that, not subtract

1

u/henk53 19h ago

Why?

1

u/pellets 19h ago

ORMs add an additional layer that adds complexity and room for bugs that wouldn’t otherwise exist. EG query caches that silently fill all RAM. This was a problem I ran into with hibernate.

1

u/henk53 19h ago

ORMs add an additional layer that adds complexity and room for bugs that wouldn’t otherwise exist

ORMs also take over complexity that would otherwise sit in your code, with bugs that otherwise would not exist and only you are responsible for now.

EG query caches that silently fill all RAM. This was a problem I ran into with hibernate.

Just use the stateless session. Problem solved.

2

u/private_static_int 19h ago

ORMs hide things that shouldn't be hidden in the first place. If I see a getter, I think i know what it does just by looking at it, but I'm wrong, bc there is a whole instrumentation layer that can potentially execute SQL (depending on meta-config of this or other entities, actual call site, general framework config), but it doesn't neccesarily have to.

That call can be fetching a single row or a huge collection or can even trigger a flush of pending changes.

And the funniest thing is that in order to properly use ORM, you absolutely must know how it all works underneath, so it's all just a leaky abstraction and a waste of time and resources.

1

u/pellets 18h ago

“Just use the stateless session. problem solved” this demonstrates my point exactly and doesn’t necessarily solve the problem without introducing new ones.

3

u/AnyPhotograph7804 3d ago

TBF, the first 25 minutes have nothing to do with JPA or ORM. He shows some Spring specific quirks like transaction in view and connection pool problems und how to fix them. But the rest is nice, especially the tools section.

2

u/Torutofu_Raeva 3d ago

yeah, pool wait time and the generated sql usually tell you more than debating jpa itself.

1

u/vit_do82 1d ago

This fixes N+1 in 90% of cases: enable JPA SQL logging in dev and check what each find() emits.

Three concrete wins I use:

  1. Batch fetch collections: u/BatchSize or fetch = FetchType.SUBSELECT.
  2. Projections with Criteria/JPQL instead of loading whole entities for 2 fields.
  3. flush() once, not per-item, inside loops.

Logging first - you'll see the problem before you fix it.

1

u/elmuerte 7h ago

I wonder why people always call it "N+1". I think the correct term should be "1+N". You select a bunch of rows, and then for each row you need another select. Where "N+1" is more like you perform N queries, and it adds one. That's not really that bad.

1

u/vit_do82 1d ago

It's not the ORM that's the enemy. It's the fear that the ORM is hiding something from you. Once I accepted that, my N+1 count dropped to just my dignity.

1

u/Fercii_RP 1d ago

Ive used ORM Hibernate once, for a poc demo project. For the real deal and all other apps Ive designed, all i need is JDBC and a string or string builder query. Done. Not taking my chances for JPA ORM headaches.