Most effective way to reflect inheritance relation

2020-06-06 02:17发布

问题:

Working on a business application using MVC structure and a Business Object / DAO architecture. For any normal business object, the CRUD functions are fairly straightforward. But what's the best way to handle a parent-child relationship like "Customer is a User"?

I know that the following classes are involved:

User, UserDAO, Customer, CustomerDAO

The Customer class can inherit from the User just fine, but how do you best reflect this in the DAO CRUD functions?

回答1:

Martin Fowler has documented a few Object-Relational Structural Patterns that might help:

1) Single Table Inheritance: Represents an inheritance hierarchy of classes as a single table that has columns for all the fields of the various classes.

e.g. Employee and Customer both inherit from User and are both stored in the User table, with a column that determines what type of user a particular record represents.

2) Class Table Inheritance: Represents an inheritance hierarchy of classes with one table for each class.

e.g. Employee and Customer both inherit from User and there are three tables to represent this. The User table stores the properties common to all users. The Employee table has a pointer to the User table and only stores the properties relevant to Employees. The same is true of the Customer table.

3) Concrete Table Inheritance: Represents an inheritance hierarchy of classes with one table per concrete class in the hierarchy.

e.g. Employee and Customer both inherit from the abstract User class and there are two tables to represent this. A Customer table and an Employee table. Each table stores information common to users, but also stores unique properties.



回答2:

You can have an instance of UserDAO in CustomerDAO. You need to interact with both the User and Customer tables to cover the base class and subclass columns. For example:

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);
    }
}

Of course, each Customer operation should probably be wrapped in a transaction so that updating the User and Customer tables does not fail independently.