Самый эффективный способ отразить отношения наследования в DAO?

Работа над бизнес-приложением с использованием структуры MVC и бизнес-объекта / DAO архитектура. Для любого обычного бизнес-объекта функции CRUD довольно просты. Но как лучше всего справиться с отношениями родитель-потомок, такими как «Клиент — это пользователь»?

Я знаю, что задействованы следующие классы:

User, UserDAO, Customer, CustomerDAO

Класс Customer может прекрасно наследоваться от User, но как лучше отразить это в функциях DAO CRUD?


person user456584    schedule 12.02.2011    source источник
comment
У вас есть две таблицы -- Users и Customers? Я был бы удивлен. Я бы подумал, что таблица users с полем user_type. А то иметь только один ВО т.е. Users. И если user.isCustomer() верно, то это клиент. Итак, либо вы не должны использовать две таблицы, либо вы не должны использовать наследование.   -  person Nishant    schedule 12.02.2011
comment
@Nishant: Это совсем не так. Если у клиентов есть дополнительные данные, которых нет у пользователей, вы будете загромождать таблицу пользователей ненужными столбцами. Конечно, можно реализовать наследование с двумя таблицами.   -  person Matt H    schedule 12.02.2011
comment
@Matt Я не говорю о возможности, я больше думал о дизайне. Клиент — это пользователь, и неплохо иметь их обоих в одной таблице. Это поможет в поиске плюс имеет больше смысла для меня. Если вы беспокоитесь о беспорядке, вынесите посторонние данные наружу. Создайте отдельную таблицу customer_details и свяжите ее с внешним ключом. Во многих сценариях вы можете захотеть превратить пользователя в клиента. Проще просто изменить тип вместо того, чтобы копировать данные между таблицами, а затем стирать прежние. Только мои 2%.   -  person Nishant    schedule 13.02.2011
comment
@user456584: blogs.tedneward.com/2006 /26/06/   -  person SyntaxT3rr0r    schedule 13.02.2011


Ответы (2)


Мартин Фаулер задокументировал несколько объектно-реляционных структурных шаблонов, которые могут помочь:

1) Наследование одной таблицы: представляет иерархию наследования классов в виде одной таблицы, в которой есть столбцы для всех полей различных классы.

например Employee и Customer оба наследуются от User и оба хранятся в таблице User со столбцом, который определяет, какой тип пользователя представляет конкретная запись.

2) Наследование таблиц классов: представляет иерархию наследования классов с одной таблицей для каждого класса.

например Employee и Customer оба наследуют от User, и есть три таблицы для представления этого. В таблице User хранятся свойства, общие для всех пользователей. Таблица Employee имеет указатель на таблицу User и хранит только свойства, относящиеся к Employees. То же самое относится и к таблице Customer.

3) Наследование конкретной таблицы: представляет иерархию наследования классов с одной таблицей для каждого конкретного класса в иерархии.

например Employee и Customer оба наследуют от абстрактного класса User, и для его представления есть две таблицы. Таблица Customer и таблица Employee. Каждая таблица хранит информацию, общую для пользователей, но также хранит уникальные свойства.

person Brandon    schedule 12.02.2011
comment
Спасибо. Это полезно. Итак, я использую № 2. Любые мысли о том, как лучше всего реализовать функции CRUD для сотрудников/клиентов/пользователей в рамках наследования таблиц классов? - person user456584; 12.02.2011
comment
Рад, что вы нашли этот пост полезным! Мне нравится идея Мэтта обернуть UserDAO внутри CustomerDAO. - person Brandon; 13.02.2011

У вас может быть экземпляр UserDAO в CustomerDAO. Вам необходимо взаимодействовать с таблицами User и Customer, чтобы охватить столбцы базового класса и подкласса. Например:

public class CustomerDAO
{
    UserDAO userDao;

    // ... initialization ...

    public void update(Customer customer)
    {
        // ... first execute update of customer table ...

        userDao.update(customer);   // Should be able to pass Customer to UserDAO due to inheritance
    }

    public void insert(Customer customer)
    {
        // First insert a row in the User table so that the ID of the user can be determined.
        userDao.insert(customer);

        // ... Now execute insertion of row into Customer table ...
    }

    public void delete(Customer customer)
    {
        // ... first delete Customer row ...

        // Now delete base class User row.
        userDao.delete(customer);
    }
}

Конечно, каждая операция Customer, вероятно, должна быть заключена в транзакцию, чтобы обновление таблиц User и Customer не завершилось сбоем независимо друг от друга.

person Matt H    schedule 12.02.2011