简体   繁体   中英

How to implement “is–a” relationship when parent and child have separate Ids

I have 2 tables: person and user. Each user is a person. Each person is not a user.

Each table has its own PK. This is the DDL of the tables:

CREATE TABLE person (
    person_pk int NOT NULL PRIMARY KEY,
    first_name varchar(50) NOT NULL,
    middle_name varchar(50) NULL,
    last_name varchar(50) NOT NULL
);

CREATE TABLE user (
    user_pk int NOT NULL PRIMARY KEY,
    user_name varchar(50) NOT NULL UNIQUE,
    password varchar(255) NOT NULL,
    person_fk int NOT NULL FOREIGN KEY REFERENCES person(person_pk)
);

Now I want to define the "is–a" relationship of person and user in OOP. I thought it would be straightforward by defining 2 classes: Person class and User Class this way:

public class Person {
    ...
}

public class User extends Person {
    ...
}

But I am confused about how to handle Id in this case. I thought that in "is–a" relationship there is only 1 Id which is defined in Person class. But in this case each table has its own Id. How can I implement "is–a" relationship in this case?

The data mode is not defined as an "is-a" relationship, it's really a 1-to-many where 1 person can be associated with multiple users. True, you can enforce via business rules a 1-to-1 relationship but it's really not.

As it stands, you truly have two different IDs which you were hoping to treat as a single entity, but really can't be. The best I can come up with is to put the attributes in the classes just as they're mapped via data, and when you're dealing with the person you'll access the ID in the parent class/table and when you're dealing with the user ID in the child class/table.

However, by no means is this a clean design.

One way to do what you describe is to redefine your tables this way:

CREATE TABLE person (
    id int NOT NULL PRIMARY KEY,
    first_name varchar(50) NOT NULL,
    middle_name varchar(50) NULL,
    last_name varchar(50) NOT NULL
);

CREATE TABLE user (
    user_name varchar(50) PRIMARY KEY,
    password varchar(255) NOT NULL,
    person_fk int NOT NULL UNIQUE,
    FOREIGN KEY (person_fk) REFERENCES person(id)
);

the defined PK in the table user is totally unnecesary, as you have a user_name which is already NOT NULL and UNIQUE, which is the basic definition of a primary key.

Also defining person_fk as NOT NULL and UNIQUE, you are establishing a 1 to 1 relationship between user and person, so this way you can use the primary key of person to identify a record in table user.

This way you can implement your classes like this:

public class Person {
    protected final int id;
}

public class User extends Person {
    ...

    public int getID() { return this.id }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM