Два перечисленных вами варианта не являются взаимоисключающими у вас может быть слой DAO / Repository, к которому вы получаете доступ через некоторый интерфейс / API, в то время как конкретные реализации внедряются во время выполнения для удовлетворения ваших зависимостей.
Например, напишите WidgetRepository интерфейс, который определяет часть виджета вашего API доступа к данным. Затем вы можете предоставить FileSystemWidgetRepository , HibernateWidgetRepository , XmlWidgetRepository , JpaWidgetRepository и т. Д., Реализующий ваш интерфейс.
Общее правило заключается в том, чтобы использовать как можно более высокий уровень абстракции при выполнении ваших требований. В приведенном мною списке примеров репозиторий на основе JPA будет наивысшим уровнем, поскольку он абстрагирует даже среду ORM.
Затем вы можете сохранить ссылку WidgetRepository в ваших объектах, которые ее используют. Код только против этого интерфейса. Затем создайте Dependency Injection фреймворк, подобный Spring , который будет внедрять конкретную реализацию WidgetRepository во время выполнения на основе некоторой конфигурации XML или механизма автоматического подключения.