Можно использовать представления со стороны БД, либо фабрики хранилищ со стороны кода.
Модно сначала просто статически запечь в отдельный класс, если это действительно узкое место. Если паттерн себя проявит, то можно оформить в виде фабрики.
Вон в C# в Entity Framework почти как вы сказали, только там запрос конструируется из коллекций классов, которые умеют в маппинг конкретной предметной области. Но там на выходе уже полноценная ORM с оптимизациями типа отложенного запроса к БД: технология Linq-To-Entity реализует реляционную логику, так что громоздкий SQL запрос модно отложить до самого последнего момента.