简体   繁体   中英

What is a good persistence design for this entity hierarchy?

I'm new to JPA and trying to work out the design for the following classes. All classes have equals and hashcode overriden, getters and setter and empty constructor.

I have a base class for all entities:

public abstract class BaseEntity {
    protected Point loc;
    protected List<Property> properties = new ArrayList<>();
}

The Point class is just the standard xy holder

public class Point {
    private int x, y;
}

And the Property class holds a name and an id:

public class Property {
    private int id;
    private String name;
}

There are 3 classes that inherit from BaseEntity . The first one is House. A House can hold a single family.

public class House extends BaseEntity {
    private Family family;
}

public class Tree extends BaseEntity {
    private String name;
}

Family will be show soon. The second one is the superclass for all the living entities:

public abstract class LivingEntity extends BaseEntity {
    public static enum Status { ALIVE, DECEASED }
    int id;
    Status status;
}

which includes

public class Family extends LivingEntity {
    private House house;
    private List<Minion> members;
}

and

public class Member extends LivingEntity {
    private Family family;
    private String name;
}

So the hierarchy graph is

    BaseEntity
        |
       /|\
      / | \
     /  |  \
House Tree  LivingEntity
                |
               / \
         Family   Member

and the composition graph is

House <---> Family ---> {Member, Member, Member, ...}
               ^           |       |       |
               |----------------------------

in addition to what they inherit.


House and Tree are identified by their location (in the equals method) so I think I can use that as the @Id . I could give them a specific id field but it's redundant.

This means that I need to make Point an entity also with a composite ID from its x and y. I don't know if this will cause the same point to be saved multiple times across the DB. I will have different sets of BaseEntities saved, so if 2 are at the same Point will it duplicate the point entry or refer all to one place?

Family and Member are defined by their id because they can move from house to house. So I want to use id in LivingEntity as the @Id but I it will cause a conflict with the @Id from BaseEntities.

Here are the annotations I have:

@MappedSuperclass
public abstract class BaseEntity {
    @Id
    protected Point loc;

    @OneToMany
    protected List<Property> effects = new ArrayList<>();
}

@Entity
@IdClass(value = PointID.class)
public class Point {
    @Id
    private int x, y;
}

class PointID {
    int x, y;
}

@Entity
public class Property {

    @Id
    protected int id;

    protected String name;
}

@Entity
public class House extends BaseEntity {
    @OneToOne
    private Family family;
}

@Entity
public class Tree extends BaseEntity {
    private String name;
}

@MappedSuperclass
public abstract class LivingEntity extends BaseEntity {
    public static enum Status { ALIVE, DECEASED }

    @Id
    int id;

    @Enumerated(EnumType.STRING)
    Status status;
}

@Entity
public class Family extends LivingEntity {
    @OneToOne // bidirectional? specify mappedBy?
    private House house;

    @OneToMany
    private List<Minion> members;
}

@Entity
public class Member extends LivingEntity {
    @ManyToOne // bidirectional? specify mappedBy?
    private Family family;

    private String name;
}

Except for the conflict of the 2 @MappedSuperclass I don't know if I'm using the annotations correctly and in a smart way. What would be a good design for this case?

I don't know your business reasons (it seems strange to have a an 'alive' or 'deceased' status for an entire family instead of just individual members), but for the example given, it seems more realistic to have something like:

BaseFixedObject  -> Point
        |
       /|
      / |
     /  | 
House Tree

LivingEntity  -> many Properties
        |
       /|
      / |
     /  | 
Member  | 
     Family  -> many Members


Property -> many BaseFixedObjects 

Property would then be mostly a collection of assets on a property - A house with a yard that may have many trees. I don't know if it would reference the Point, or each tree/house has its own point - it depends on your need. Or you can do away with Property and have LivingEntity reference BaseFixedObjects directly.

The relationships might be bidirectional, so a property may reference the LivingEntity that it is tied to, which would be a single 'member' or Family. I'm not sure if joint ownership is required outside of families in this model - if it is, a Property might need to allow more than one owner, making it a ManyToMany relationship.

This way, your family (likely) has a house that has a fixed point. It doesn't need to reference the point itself, as you have access to it through the associated properties.

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