If you just want to store and retrieve objects, and then store and retrieve "related" objects, what you want is an object store, not a relational database. You can use an ORM to shoehorn it into a relational database engine, but don't fool yourself into thinking that's the same thing as using a relational database engine properly.
Obsessively cramming tabular data into objects is often unnecessary, and it bloats the code downstream of the database query. It then encourages the bad habit of performing data manipulation in code rather than directly in the database.
"Fetch related objects" is a code smell. If any related data was needed, your original query should have already fetched it.
Problem is that doesn't work nicely in a one-to-many or many-to-many relationship - fetching it in the original query means deduplicating in the application code, or not fetching it and getting related rows afterwards. And that's one of the things ORMs are really good at.
For a video game, simulation, CAD program or other stateful program, loading an object graph can be natural. In that context, an object store, document database, serialized state, or ORM-backed persistence layer may be a reasonable fit. This isn't database design, it's application design.
But in data management applications, the job is to derive specific information from stored facts. For that, SQL is not an implementation detail behind objects; it is the main abstraction. The whole point is to ask for the shape of data your application actually needs, not to arbitrarily hydrate objects and reinvent a bespoke querying engine on the client side. I can barely even remember the number of times that I've ripped an ORM out of a system because the code to interact with hydrated objects had devolved into a single-purpose database engine, a sprawling mess of code, seemingly well organised into objects, but ultimately wasteful.
Often, de-duplicating in code is a perfectly fine solution, and significantly more performant than multiple round-trips. A join that repeats parent columns is not a flaw in SQL. It is only a problem if the application insists on rebuilding a nested object graph instead of asking for the shape of data it actually needs.
If the data returned by the query does not match what you are presenting, the answer should not be to fetch a pile of related objects and interrogate them in memory. It is to use more SQL to further digest the data so that the result set more closely matches what you intend to present to the user.
Obsessively cramming tabular data into objects is often unnecessary, and it bloats the code downstream of the database query. It then encourages the bad habit of performing data manipulation in code rather than directly in the database.
"Fetch related objects" is a code smell. If any related data was needed, your original query should have already fetched it.