Databases are a shared resource. Most programmers think of them as private property. My job as a DBA for many years was to "direct trafic" at this busy data highway intersection. John Wu's answer is on the right track.
There needs to be a layer of code between the application and the database. That layer caches the data going both ways. To the application, it looks like its own private datastore. To the database, it looks like one or a very small number of reads and writes.
Ideally... the database would get 1 SELECT at the beginning of the transaction and return all the data from all the tables that the application needs. That way, the very expensive and incredibly optimised database engine can use it's intimate and continually changing knowledge of the data to retrieve that infinitesimal subset of records in the fastest and most efficient way possible.
For example, if a table had only a few thousand rows and you have the memory, cache the whole table in RAM and do full table scans. Ignore the indexes since the double fetches would slow things down.
If all the columns needed are in indexes, then ignore the data tables and read just the indexes. Since indexes are often changed by the DBAs as part of the continuous tuning process, there's no way for the application to take advantage of this though.
No programmer, anywhere, regardless of skill, has the slightest chance of doing all this better because we do not and cannot analyze the data, this minute, the way the database engine can.
So, the selected data would be cached and constitute the entire body of data the application can manipulate in this transaction. If no application server is in use to do the caching, it can, and often is done using database stored procedures.
It could also be done by the application... but that way "there be dragons". The application programmer simply does not have access to all the information needed to write an efficient and reliable "middleware" layer. It may work for small databases, but it won't scale. It will quickly become the #1 bottleneck in the system. Don't do it.
Once all the edits to the cached data are completed, this middle layer writes the new data back to the database in the most efficient way possible in order to maximize performance. It's tempting to say that it should be 1 write, but that's rarely wise... or even possible.
The approach used is highly variable. It depends on the number of tables involved, quirks and features of the database engine, current load on the system, volumetrics, and business rules for how current the data must be.
Regarding the latter, recognize that not everything has to happen right now. The most efficient way to make database changes is with overnight "batch jobs"... long running programs doing bulk INSERT, UPDATE and DELETEs of all changes from that day.
(Introduction to Smoke and Mirrors -- That 1 query done at the beginning? Under the covers it would often actually be 2 queries. One to the main database, and one to a set of transaction tables holding recent changes that will be applied to the main database by a long-running-process later when there aren't thousands of users banging on it.)