Я видел и работал со многими старыми кодами DAO на основе JDBC, которые обычно начинаются с методов CRUD. Мой вопрос относится конкретно к методам поиска или «искателям». Обычно я обнаруживаю, что DAO начинают с двух методов:
- найти и вернуть ВСЕ
- получить конкретный экземпляр на основе уникального идентификатора
Чаще всего этих двух искателей недостаточно. Обычно я вижу, что класс DAO неоднократно модифицировался, чтобы добавить методы поиска, подобные следующим:
- найти и вернуть ВСЕ, где {условие}
Что происходит, так это то, что добавляются дополнительные методы, когда необходимо поддерживать новые {условия} или существующие методы модифицируются для добавления новых параметров в качестве флагов для изменения SQL-запроса внутри метода для поддержки дополнительных условий.
Это уродливый подход, который нарушает принцип открытого-закрытого. Меня всегда раздражало, что классы DAO постоянно модифицируются всякий раз, когда необходимо поддерживать какое-то новое условие поиска. Исследования по этому вопросу часто указывают мне на шаблон репозитория и инкапсуляцию условий для извлечения в виде спецификаций или объектов запроса, а затем их передачу. методу поиска. Но это кажется возможным только в том случае, если у вас есть коллекция всего набора данных в памяти или если вы используете какой-то ORM (я работаю со старым кодом JDBC)
Я рассмотрел решение, которое лениво загружает весь набор данных, которым управляет DAO, как коллекцию в память, а затем использует шаблон спецификации в качестве запросов для извлечения. Затем я реализую какой-то наблюдатель в коллекции, который просто обновляет базу данных при вызове методов создания, обновления или удаления. Но очевидно, что производительность и масштабируемость значительно страдают.
Есть мысли по этому поводу?
Спасибо за ответы. У меня есть одна мысль: каково ваше мнение об использовании шаблона Command/Policy для инкапсуляции запросов на доступ к данным? Каждая отдельная конкретная команда может представлять определенный вид доступа и может быть передана Invoker. Я бы закончил с многочисленными классами Concrete Command, но каждый из них будет ориентирован только на один вид доступа и должен быть хорошо тестируемым и изолированным.
public abstract class Command<R>{
public <R> execute();
public void setArguments(CommandArguments args){
//store arguments
}
}
//map based structure for storing and returning arguments
public class CommandArguments{
public String getAsString(String key);
public String getAsInt(String key);
//... others
}
//In some business class...
Command command = CommandFactory.create("SearchByName");
CommandArguments args = new CommandArguments();
args.setValue("name", name);
// others
command.setArguments(args);
List<Customer> list = command.execute();