pull down to refresh
21 sats \ 2 replies \ @franzap 29 Jun 2023 \ parent \ on: Is ORM still an anti-pattern? tech
Why? (Never tried it)
I am going to use responses from other people since I can't explain it better than they already did:
I've been doing ORM on Java since Hibernate was new, and it has always sucked. One of the selling points, which is now understood to be garbage, is that you can use different databases. But no-one uses different databases. Another selling point which is "you don't need to know SQL", is also garbage. Every non-trivial long-lived application will require tweaks to individual queries at the string level. The proper way to build a data layer is one query at a time, as a string, with string interpolation.
Couldn't agree with this more. The way I like to put it is "ORMs make the easy parts slightly easier, but they make the hard parts really hard". But I don't care that much about improving the easy parts, because they're already easy! Yet I can remember plenty of times when ORMs made my job a million times more difficult and all I was doing was fighting with the ORM itself (and usually at the worst time, e.g. when a query reached enough scale that it "fell over").
For example, I am not sure if this code from the article even works:
const postRepository = connection.getRepository(Post); await postRepository .createQueryBuilder() .update(Post) .set({ status: 'archived' }) .where("authorId IN (SELECT id FROM author WHERE company = :company)", { company: 'Hooli' }) .execute();
According to the docs, subqueries should be created like this:
const postRepository = connection.getRepository(Post); await postRepository .createQueryBuilder() .update(Post) .set({ status: 'archived' }) .where(qb => const subQuery = qb .subQuery() .select("author.id") .from(Author, "author") .where("author.company = :company") .getQuery() return "post.authorId IN " + subQuery ) .setParameter("company", "Hooli") .execute();
And even then, TypeORM would find a way to complain. For example, TypeORM was not consistent in using quotation marks (at least when I used it). So it could be that this query above still not works, because
authorId
is not quoted. But this should finally work (maybe):- return "post.authorId IN " + subQuery + return 'post."authorId" IN ' + subQuery
And if it doesn't complain, it will create a really weird SQL query since it doesn't understand enough about your schema so it can't assume some things so it builds a query which is not exactly what you expect. But the query may return correct results first. Then you hit production and you get weird results.
So at the end, I had to know anyway how my SQL query should look like so it does exactly what I want, in 100% of the cases. And then I had to fight with TypeORM to generate this query. And then some more to get some acceptable performance.
At the end, I ditched it for
knex
and a few months later another team also ditched it and we never looked back.There was also a hilarious issue in their Github where someone complained that he lost all rows in a table because a parameter he used to select rows was undefined and thus his
.where("id", id)
was silently dropped. The maintainer said this was not a bug but expected behavior. Wasn't able to find it between all these issues.You see, I had a lot of fun with TypeORM, lol
reply
Haha sounds like a lot of fun!
Okay this answers my question, it's a pain with SQL. I'm guessing no easy way of writing raw SQL.
What I do like about these libraries is the data modelling and relationships/graph support.
reply