То есть, "обжегшить на молоке... дуем на воду"?
Возможно

У меня очень богатый опыт работы с кодом в стиле "ООП ради ООП".
Зачем надо каждый раз переопределять ВСЕ методы, если требуется добавить один новый или переопределить один существующий?
Нельзя переопределить один существующий. Я тут согласен с Ильей - переопределяешь все и берешь на себя ответственность за каждый (хотя я бы хотел иметь в языке сахар для редиректа). Накушался я такого подхода. Есть базовый класс, который вызывает в какой-то последовательности перегруженные методы. И есть наследники, которые "подстраиваются" так, чтоб это все в итоге работало. Со временем это все обрастает соплями, потому что, естественно, на момент написания базового класса всех возможных особенностей наследников не было предусмотрено. И поменять в базовом уже ничего нельзя, потому что есть какое-то количество наследников (и наследников наследников), которые завязаны вот точно на такое "нелогичное" (со свежей точки зрения) дергание методов из базового класса. Чего-то рефакторить уже бесполезно, нужно по крупицам (прыгая по всей цепочке наследования реализации) собирать воедино всю логику (попутно избавляясь от хэков, которые заставляли все это работать) и писать просто заново. Без наследования и без надуманных иерархий. В итоге, когда все распутано, кода оказывается в
разы меньше, а главное сразу видно что откуда, куда и как работает.
Конечно можно сказать, что с самого начала базовый класс делал херню и можно было сделать по-нормальному. Но я предпочитаю другой подход. Просто не плодить иерархий, пока без них ну вот никак. И что интересно, таких случаев (когда никак) исчезающе мало.
Конкретный пример. Если вам хочется перегрузить виртуальный метод (один), чтобы изменить один аспект поведения в наследнике - ну вынесите этот аспект в отдельный колбэк. А если у вас несколько аспектов - то получится небольшой и понятный интерфейс. От такого подхода (без наследования только ради возможности менять поведение базового класса) вы получите пользу прямо здесь и сейчас - вы сможете тестировать (юнит) ваш аспект даже если базовый класс тестированию не поддается (потому что это гуйня или какая-нибудь база данных). Это помимо отсутствия будущей головной боли, если вы простой человек и таки не смогли задизайнить правильно базовый класс с самого начала

Предположим, что мы реализовали класс "Текстовая Строка", от неё можно наследовать классы специфических строк, например URL, e-mail и пр. При этом вся логика работы со строками сохраняется... Зачем всё переписывать?
Не знаю как применительно к базе данных, но в общем случае наследование емыла от строки выглядит крайне странно.