разработка API взаимодействия с базой данных для вставки и удаления объектов домена

Я пытаюсь создать хороший дизайн ООП, особенно соответствующий SRP для взаимодействия с базой данных для вставки и удаления Customer. Я сосредоточен на дизайне, а не на деталях SQL и JDBC или источниках данных. Поэтому я оставил простые реализации с использованием линий печати. Но мне интересно, так ли спроектирован Springs jdbctemplate.

Эта попытка возникла, когда я изучал принцип проектирования SRP OOP. Плохо спроектированный класс Customer нарушил SRP, поскольку содержал ответственность за вставку/удаление базы данных. Я вытащил код из класса Customer и поместил его в класс, наследуемый от базового класса RdbmsManager, который отвечает за установление соединений и взаимодействие с базой данных. Я не уверен в том, что это хороший дизайн, и я также не уверен, что какой-то объект API базы данных, похожий на jdbcTemplate, или что-то еще нужно предоставить дочерним классам для взаимодействия с базой данных.

Customer класс

public class Customer {

    private int id;
    private String fullName;
    private boolean active;

    public Customer(int id, String name, boolean active){
        this.id = id;
        this.fullName = name;
        this.active = active;
    }

    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", active=" + active
                + "]";
    }   
}

Класс доступа к родительской базе данных:

public class RdbmsManager{

    public RdbmsManager(){
           connectToDatabase();
    }

    private void connectToDatabase(){
           // read from properties files to get DB URL, PORT number etc.
           // Create Datasource object and establish connection to database
           System.out.println("Established Database Connection...");
    }

   // Below method returns the database object children can use to issue commands
    protected DatabaseAPI getDatabaseObject(){
        DatabaseAPI databaseObject = new DatabaseAPI ();
           return databaseObject;
    }

}

Дочерний класс CustomerDataManager:

public class CustomerDataManager extends RdbmsManager{

    public CustomerDataManager() {
        super(); // call to super will establish database connection from parent class
    }

    public void saveCustomerToDatabase(Customer Customer) {
        getDatabaseAPI().insert(Customer);
    }

    public void deleteCustomerFromDatabase(Customer Customer) {
        getDatabaseAPI().delete(Customer);
    }
}

Простая реализация объекта взаимодействия с базой данных, чтобы сосредоточиться на дизайне:

public class DatabaseAPI{

    protected void insert(Object object){
           System.out.println("inserted the into the database: "+ object.toString());
    }

    protected void delete(Object object){
           System.out.println("Deleted object from database" + object.toString());
    }
}

person Horse Voice    schedule 21.08.2014    source источник
comment
почему этот вопрос был запрошен для закрытия ??   -  person Horse Voice    schedule 21.08.2014


Ответы (1)


Что ж, вы довольно близко подошли к одному из стандартных подходов к работе с базами данных.
Основное отличие заключается в названии классов (например, DAO вместо Manager) и в том, что вы расширяете пул соединений с БД. менеджер для создания DAO.

Позвольте мне немного уточнить:

  1. База данных должна быть отделена абстракцией от вашего приложения. Чтобы достичь этого, вы обычно создаете то, что известно как data abstraction layer поверх базы данных. Это немного похоже на ваш класс RdbmsManager, и его цель состоит в том, чтобы абстрагироваться от фактической используемой БД. Для этого у вас обычно есть какой-то интерфейс доступа к базе данных, который будет реализован каким-то классом, контролирующим все соединения с БД (старайтесь избегать имен, содержащих «Менеджер», поскольку это на самом деле не помогает понять, что делают эти классы. ). Если позже вы решите изменить используемую БД, все, что вам нужно сделать, это создать новую реализацию интерфейса, поддерживающего новую БД, и все готово!

  2. Доступ к фактическим данным в базе данных также должен быть абстрагирован другим уровнем, обычно называемым data access layer. Этот уровень содержит интерфейсы, которые инкапсулируют весь доступ к данным определенного типа (обычно для каждой таблицы) и позволяют выполнять над ними CRUD операции. Эти интерфейсы обычно называются SomethingDAO, где «Что-то» означает тип объекта, к которому осуществляется доступ (часть «DAO» означает: «Объект доступа к данным»). Опять же, реализации этих интерфейсов должны быть специфичными для БД и изменяться при замене используемой БД на другую.

  3. Данные должны быть переданы в клиентский код (обычно уровень бизнеса/приложения) с использованием какого-либо другого метода, обычно DTOs (расшифровывается как «Объект передачи данных»). Это (опять же) интерфейсы, которые предоставляют некоторые функции, необходимые для объектов, представленных в БД, которые должны быть реализованы специфическими (или общими, в зависимости от этого) классами БД.

Это теория вкратце. В Интернете есть много источников данных (не говоря уже о книгах), которые позволят вам прочитать об этом гораздо больше.

С другой стороны, это всего лишь один из способов реализации подключения к БД. Есть множество других, поскольку существует множество шаблонов проектирования, которые относятся к корпоративным приложениям в целом и к межуровневому взаимодействию в частности. Позвольте мне сослаться на то, что я считаю лучшим источником этих шаблонов проектирования: Шаблоны архитектуры корпоративных приложений

Редактировать 1: Вот действительно упрощенный пример кода (конечно, непроверенный — считайте его псевдокодом):

public interface Customer { ... }

public interface CustomerDTO implements Iterable<Customer> { ... }

public class CustomerDTOSQLImpl {
    public CustomerDTOSQLImpl(ResultSet resultSet) { ... }

    @Override
    public Iterator<Customer> iterator() { ... }

    ...
}

public interface CustomerDAO {
    public CustomerDTO findById(int id);

    ...
}


public class CustomerDAOSQLImpl {
    @Inject
    private Connection connection;

    @Override
    public CustomerDTO findById(int id) {
        PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMER WHERE ID = ?");
        statement.setInt(1, id);
        return new CustomerDTOSQLImpl(statement.executeQuery());
    }

    ...
}
person ethanfar    schedule 21.08.2014
comment
Спасибо. В основном я хочу убедиться, что CustomerDataManager или CustomerDAO, как вы предлагаете, не должны меняться при изменении базы данных. Достигнет ли этот дизайн такого уровня абстракции? - person Horse Voice; 21.08.2014
comment
Что ж, «CustomerDAO» не изменится, но вам придется добавить новый класс «CustomerDAOImpl» для каждого поддерживаемого типа БД. Я не думаю, что есть способ создать единую общую реализацию. - person ethanfar; 21.08.2014
comment
Хм, не могли бы вы рассказать подробнее о дао и реализации дао. Не могли бы вы показать пример кода для этого? - person Horse Voice; 21.08.2014
comment
Должен ли я действительно расширяться от менеджера? Я думаю, может быть, мне следует сделать DatabaseManger синглтоном, который предоставляет единственный экземпляр объекта Connection. С точки зрения дизайна, что бы вы сказали лучше? - person Horse Voice; 22.08.2014
comment
Это точно. Диспетчер БД должен быть одноэлементным и обеспечивать подключение БД к DAO (предпочтительно через инъекцию). - person ethanfar; 22.08.2014