I wasn't sure whether to put this is the design forum or here. I think my design is about right, but I can't figure out how to implement it in JPA (or underlying native hibernate).
My application focuses on handling registration for ballroom dance competitions. The simplest domain model would look something like
Event: A single competitive event. Most Competitions will have 10s to 100s of events.
Entry: A single registration of a Couple for an Event
Couple: The basic
unit of registration, composed of two People in named roles (leader/follower)
Person: no explanation required
Event-1:M-Entries-M-1-Couple-M:2-Person
This would cover 95% of the cases. However there are other "units of registration" -- Team Match Teams (3-6 Couples form a single team, each couple has an assigned dance), Formation Teams (3-10 Couples, no specified ordering or role), and Production Number Squad (1+ People). I've been calling the superset of these "RegistrationEntities" -- I hate the term, since its outside the common domain language... but we don't have a term for this superset in the domain...
I was thinking about moving "Couple" outside of this hierarchy and introducing a "CoupleEntity" as one of the four direct subclasses. Thus CoupleEntity, TeamMatchTeam, and FormationTeam would all be able to re-use Couple(s) with the appropriate extra rules on cardinality,named roles, etc. See the attached diagram.
Two of the ManyToMany associations (betean FormationTeam and Couple, between ProductionNumberSquad and Person) can be regular bidirectional @ManyToMany. The TeamMatchTeam to Couple one needs an extra column, so will need to have an intermediate join entity.
Now the blue line stumps me -- this doesn't need to me a "real" association, but I need the equivalent functionality.
Ie, from a RegistrationEntity I can have a getMembers() abstract method, that the subclasses implement to return the set of People in that Entity. But I'm not sure how to go the other direction (which is the more important one) -- from a Person a I need a getRegistrationEntities. I don't need (nor particularly want) exposed "getCouples" nor "getProductionNumberSquads" (actually I do want a getCouples, but it should return only Couples that occur in CoupleEntities.... so its not the raw collection underlying the join of the Leader and Follower associations)
I had been playing with a version were I dropped "Couple" and all the RegistrationEntity subclasses and simply put in a "RegistrationEntityMembership" intermediate join table (regent_id, person_id, role). While I can get that system to work, that object model is so far removed from the real domain model everything else becomes painful.
Now the next approach I could try is to expose a getRawCouples() and getProductionNumberSquads() on Person (needed to allow proper bidirectional synchronization when adding a person to a couple, etc), and then build both a "getCouples" and a "getRegistrationEntities()" query from those primitive methods with suitable filtering... Of course the getCouples will be a highly used called, so I'll have to add some memoization, etc...
Is this the "right" way forward for this kind of model where we have a polymorphic collection type holding variable number of base units in subclass specific constraints and the base units needs a link back to all containers?