Some backend libraries let you write SQL queries as they are and deliver them to the database. They still handle making the connection, pooling, etc.

ORMs introduce a different API for making SQL queries, with the aim to make it easier. But I find them always subpar to SQL, and often times they miss advanced features (and sometimes not even those advanced).

It also means every time I use a ORM, I have to learn this ORM’s API.

SQL is already a high level language abstracting inner workings of the database. So I find the promise of ease of use not to beat SQL. And I don’t like abstracting an already high level abstraction.

Alright, I admit, there are a few advantages:

  • if I don’t know SQL and don’t plan on learning it, it is easier to learn a ORM
  • if I want better out of the box syntax highlighting (as SQL queries may be interpreted as pure strings)
  • if I want to use structures similar to my programming language (classes, functions, etc).

But ultimately I find these benefits far outweighed by the benefits of pure sql.

60 points

You don’t even mention the 2 main advantages:

  • ORM lets you to use plain objects over untyped strings. I take typed anything over untyped anything, everyday
  • ORM lets you to use multiple database backends. For ex, you don’t need to spawn a local postgres server, then clean/migrate it after each test suit, you can just use in-memory sqlite for that. OK this has some gotchas, but that’s a massive improvement in productivity
permalink
report
reply
14 points

I too want my query results in an object, but thankfully libraries like sqlx for golang can do this without the extra overhead of an ORM. You give them a select query and they spit out hydrated objects.

As far as multiple DBs go, you can accomplish the same thing as long as you write ANSI standard SQL queries.

I’ve used ORMs heavily in the past and might still for a quick project or for the “command” side of a CQRS app. But I’ve seen too much bad performance once people move away from CRUD operations to reports via an ORM.

permalink
report
parent
reply
4 points

Even something as ubiquitous as JSON is not handled in the same way in different databases, same goes for Dates, and UUID. I am not even mentioning migrations scripts. As soon as you start writing raw SQL, I pretty sure you will hit a compatibility issue.

I was specifically talking about python, can’t argue with golang. OK you have a valid point for performance, gotta keep an eye on that. However, I am satisfied for our CRUD api

permalink
report
parent
reply
7 points

I was about to write the same thing. Really the object thing is the whole reason to use ORMs.

Using plain SQL is a compatibility and migration nightmare in medium and bigger sized projects. If anything using plain SQL is just bad software design at least in an OOP context.

permalink
report
parent
reply
4 points

Not to mention refactoring support…

permalink
report
parent
reply
3 points

There seems to be a trend of new (old) developers who find that strong typing is nothing more than a nuisance.

History repeating itself in the IT world. I don’t wanna be around to support the systems that inherit these guys.

permalink
report
parent
reply
40 points

Better than an ORM is to use a query builder. You get the expressiveness of SQL with the safety and convenience of an ORM.

Most developers that use ORMs create poorly performing monstrosities, and most developers who write raw SQL create brittle, unsafe and unmaintainable software. There is a happy medium here.

permalink
report
reply
12 points

I also find ORMs and query builders much easier to debug than most mative SQL database queries. Mostly because native SQL error messages tend to be some of the most unhelpful, most undescriptive crap out there, and ORMs help a bit with that.

Seriously, fuck MySQL error messages. 9 times out of 10 shit boils down to “you got some sort of error somewhere roughly over there, go fix”.

permalink
report
parent
reply
1 point
*
Deleted by creator
permalink
report
parent
reply
30 points

You miss the major reason of an orm, abstract vendor specif syntax, i.e. dialect and derived languages such as pl sql, t-sql, etc.

Orm are supposed to allow you to be vendor agnostic

permalink
report
reply
23 points

But then you get locked into the ORM’s much more highly specific syntax.

At least the differences across SQL variants are not THAT major from my experience. The core use cases are almost the same.

permalink
report
parent
reply
12 points
*

How many good orm do you have per language? 1? 2? Orm is practically locked once one chooses the language

permalink
report
parent
reply
4 points

Surely there’s more than 1 ORM that is at least used commonly enough to have a decent community for every major programming language. Just search the web for ORMs in python, JS, and Go and you’ll see what I mean.

Not even language choice is forever. I’ve seen more codebases change languages or frameworks than I have seen changing databases.

What if you change jobs, and now work with a different language or framework? What if you’re just helping out a sibling team in your company, and they use something different? Having to relearn a new ORM is annoying when you already know SQL.

I am not basing my argument on any of these things having a high likelihood of changing. The main point to me is that you’re abstracting an already high level and very well abstracted API, and the reasons presented don’t justify it (abstracting vendors but then locking you into a more specific vendor).

permalink
report
parent
reply
12 points

I’m always curious about this particular feature/argument. From the aspect of “i can unit test easier because the interface is abstracted, so I can test with no database.” Great. (though there would be a debate on time saved with tests versus live production efficiency lost on badly formed automatic SQL code)

For anything else, I have to wonder how often applications have actual back-end technologies change to that degree. “How many times in your career did you actually replace MSSQL with Oracle?” Because in 30 years of professional coding for me, it has been never. If you have that big of a change, you are probably changing the core language/version and OS being hosted on, so everything changes.

permalink
report
parent
reply
9 points

Some of us have had to support multiple database targets. So I don’t know about changing a database in a running application, but a good abstraction has made it easier to extend support and add clients when we could quickly and easily add new database providerz

permalink
report
parent
reply
9 points

If you are building software where the customer is the deployer being flexible on what database can be used is a pretty big step. Without it could turn off potential customers that have already existing infastructure.

permalink
report
parent
reply
8 points

Well, developing on SQLite and deploying to Postgres is a much more common scenario than migrating your data from one DBMS to another.

permalink
report
parent
reply
7 points
*

Working in a data intensive context, I saw such migrations very often, from and to oracle, ms sql, postgres, sas, exasol, hadoop, parquet, Kafka. Abstraction, even further than orms, is extremely helpful.

Unfortunately in most real case scenarios companies don’t value abstraction, because it takes time that cannot be justified in PI plannings and reviews. So people write it as it is quicker, and migrations are complete re write. A lot of money, time and resources wasted to reinvent the wheel.

Truth is that who pays doesn’t care, otherwise they’d do it differently. They deserve the waste of money and resources.

On the other hand, now that I think of it, I’ve never seen a real impacting OS migration. Max os migration I’ve seen is from centos or suse to rhel… In the field I work on, non unix OSes are always a bad choice anyway

permalink
report
parent
reply
1 point
*

Yeah, I have my own stuff that lets me do MSSQL, DynamoDB, REST/HATEAOS, regular Hash Maps, and some obscure databases (FilePro).

I throw them in a tree structure and perform depth-first searches for resources. Some of them have stuff for change data capture streaming as well, (eg: SQLNotifications, DynamoDB Stream, WebSockets).

DynamoDB was a rough one to optimize because I have to code to pick the best index. You don’t do that with SQL.

The code on backend is the same as frontend, but a different tree. Frontend queries against REST and a cache layer. Backend queries against anything, REST included.

permalink
report
parent
reply
26 points
*

Yeah, that’s great, until you need to conditionally compose a query. Suddenly your pre baked queries are not enough. So you either:

  • create your own shitty ORM based on string concatenation
  • create your own shitty ORM
  • or use a well supported ORM, those almost always support query composition and native queries

You write like it’s ORM vs native. ORMs let you write native queries and execute them while also doing all the tedious work for you such as:

  • mapping results to model objects
  • SQL injection safety
  • query composition
  • connection builders
  • transaction management

So if you love native queries write native queries in an ORM which will do all the tedious shit for you.

permalink
report
reply
4 points

Composable querying/pushdown is nice but transaction management is huge. It’s not an easy task to correctly implement a way to share transactions between methods and between repository classes. But the alternative is, your transactions are limited to individual methods (or you don’t use them, and you risk leaving your database in an inconsistent state without manual cleanup).

permalink
report
parent
reply
1 point

mapping results to model objects

I agree. If you have a relational database and an object-oriented programming language you’re going to have to map data one way or another.

That being said, using object-oriented doesn’t necessarily mean the data abstraction needs to be objects too. Python is object-oriented yet Pandas is a very popular relational abstraction for it.

SQL injection safety

Parameterized queries are native to the database engine. They’re going to be available regardless what you use on the client side.

(Well, if the database implements them… having flashbacks to back when MySQL didn’t, and it taught a couple of generations of programmers extremely bad “sanitization” practices.)

query composition

Check out the active record pattern. It’s a thin layer over SQL that lets you put together a query programatically (and nothing more).

connection builders

This is very database specific and many ORMs don’t do a great job of it. If anything this is a con for ORMs not a pro.

transaction management

Again, very hit and miss. Each database has particular quirks and you need to know so much about them to use transactions effectively that it negates any insulation that the ORM provides.

permalink
report
parent
reply
14 points

I had a job where we used Spring Boot with JPA on the backend. It was nice because you could just use the ORM methods for basic CRUD functionality. But on the other hand it has this @Query annotation we used for whenever we wanted to write our own queries. Probably against best practice but it worked well enough

permalink
report
reply

Programming

!programming@programming.dev

Create post

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person’s post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you’re posting long videos try to add in some form of tldr for those who don’t want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



Community stats

  • 2.2K

    Monthly active users

  • 1.8K

    Posts

  • 29K

    Comments