ООП Программирование с доступом к базе данных
Я работаю над проектом с доступом к базе данных. Вот схема классов, которые я реализовал
public class Foo {
private String id;
private String name;
private int x;
private String y;
private String z;
...
public Foo(String id) throws SQLException {
this.id=id;
try (Statement stmt = MyConnectionManager().getConnection().createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT * FROM " + TABLE_NAME
+ " WHERE(id='" + this.id + "')");
if (!rs.next()) {
throw new NoExistException();
}
this.name = rs.getString("Name");
this.x = ...
...
} catch (SQLException ex) {
throw ex;
}
}
public int getId() {
return this.id;
}
public String getName() {
.
.
.
Но когда я посмотрел на большинство новых образцов, я обнаружил, что большинство людей используют дополнительный класс для доступа к базе данных. Я не знаю, что я собираюсь сказать, это грубая ошибка. Эти коды обращаются к базе данных для инициализации каждой переменной-члена. Но в моем коде база данных доступна только один раз для инициализации моего объекта. Должен ли я изменить этот подход. Если я изменю это, это повлияет на скорость моего приложения, когда оно хочет инициализировать больше объектов вместе (может быть сотни). Я думаю, что это может быть вопросом дублирования. Но я не нашел удовлетворительного ответа на мою конкретную проблему.
2 ответа
Ваш подход нарушает принцип единой ответственности и разделение проблем - в основном класс не должен быть одновременно классом домена и обращаться к базе данных.
Подход, при котором каждая переменная-член инициализируется независимо и эта инициализация включает в себя вызов базы данных, еще хуже и не будет работать, а также нарушает ранее упомянутый принцип единой ответственности и разделение проблем, которые он просто не будет выполнять.
Чаще всего это делается через слой доступа к данным, где у вас есть класс, который осуществляет доступ к базе данных и отображает результирующие наборы в новые экземпляры классов вашего домена.
В вашем случае это означает, что вы получите интерфейс DAO, который может выглядеть примерно так:
public interface FooDao
{
public Collection<Foo> getAll() throws DaoException;
public Foo getByIdentity(String id) throws DaoException;
public Collection<Foo> getByName(String name) throws DaoException;
public void save(Collection<Foo> foos) throws DaoException;
}
Интерфейс может иметь серию методов get или предоставлять какой-то механизм, основанный на критериях, чтобы позволить вам создавать более сложные запросы (есть некоторый код, который я написал некоторое время назад, который делает это здесь), но важно то, что именно этот интерфейс все ваш код использует. Затем вы реализуете этот интерфейс по своему усмотрению (используя прямой JDBC, если ваша объектная модель простая, или Hibernate, если вам нужно что-то более продвинутое), или смоделируйте его в своих модульных тестах.
Когда вы вводите Bar
класс вы будете повторять шаблон, определяющий BarDao
и внедрение по мере необходимости снова.
Это выбор дизайна, некоторым людям нравится модульность их программы, это считается хорошей практикой, поскольку модификация и обслуживание не влияют на другие классы.
Если вы создаете новый класс для доступа к базе данных (рефакторинг), он также позволяет другим классам обращаться к этому классу, если им требуется доступ к базе данных.