Zum Inhalt springen

DDM_ENTITY_RELATION

Status: Entwurf · Spec-Kandidat: ja

Zweck

Konkrete Beziehung zwischen zwei DDM_ENTITY-Datensätzen, klassifiziert durch einen DDM_RELATION_TYPE. Optional zeitlich begrenzt (valid_from, valid_to). Soft Delete.

Felder

FeldTypPflichtHinweise
iduuidjaPK
tenant_iduuidjaFK → AA_TENANT, muss mit Tenant der beiden Endpunkte übereinstimmen (Trigger)
relation_type_iduuidjaFK → DDM_RELATION_TYPE
from_entity_iduuidjaFK → DDM_ENTITY
to_entity_iduuidjaFK → DDM_ENTITY
valid_fromtimestamptzneinoptionaler Gültigkeitsbeginn
valid_totimestamptzneinoptionales Gültigkeitsende
sort_orderintegerjadefault 100
attributesjsonbjadefault '{}' — fachliche Eigenschaften der Beziehung; validiert gegen DDM_RELATION_TYPE_ATTRIBUTE
metadatajsonbjadefault '{}' — technische Felder (Quellsystem-Hash, Sync-Flags)
created_at, created_by, updated_at, updated_byStandardfelder
deleted_at, deleted_bySoft Delete

Constraints

  • entity_relation_from_to_chk: from_entity_id <> to_entity_id (keine Selbstreferenz im einfachen Fall)
  • entity_relation_validity_chk: valid_from <= valid_to falls beide gesetzt
  • entity_relation_attributes_is_object_chk, entity_relation_metadata_is_object_chk
  • Partial Unique: uq_entity_relation_active auf (tenant_id, relation_type_id, from_entity_id, to_entity_id) WHERE deleted_at IS NULL

Trigger

  • trg_entity_relation_set_updated_at
  • trg_validate_entity_relation_types: prüft bei INSERT und bei UPDATE der Felder relation_type_id, from_entity_id, to_entity_id, tenant_id, dass die Entitätstypen der Endpunkte zum Relationstyp passen und beide Endpunkte sowie die Beziehung selbst zum gleichen Tenant gehören. Bei Verletzung wird die Transaktion mit Exception abgebrochen.

Indizes

  • ix_entity_relation_from (partial, aktiv)
  • ix_entity_relation_to (partial, aktiv)

Verhalten

  • Anlage erfolgt nur über den Service-Layer; UI/API muss vor Insert die Endpunkte gegen den Relationstyp prüfen, um aussagekräftige Fehler zu liefern (DB-Trigger ist Sicherheitsnetz).
  • Service-Layer validiert attributes gegen Definitionen aus DDM_RELATION_TYPE_ATTRIBUTE (Pflicht, Datentyp, Enum, Regex, Min/Max, validation_rule).
  • Soft Delete via deleted_at. Hard Delete nur administrativ.
  • Reaktivierung: nicht durch Datenmodell vorgesehen; bei Bedarf neuer Datensatz.

Bidirektionale Relationstypen — Zwei-Zeilen-Pattern

Bei DDM_RELATION_TYPE.is_bidirectional=true (siehe OP-13) schreibt der Service-Layer zwei Zeilen in derselben Transaktion:

relate(rel_type, A, B, attrs):
INSERT entity_relation (relation_type_id, from=A, to=B, attributes=attrs, ...)
INSERT entity_relation (relation_type_id, from=B, to=A, attributes=attrs, ...)
→ ein Audit-Eintrag, ein Outbox-Event (correlation_id verbindet beide)

Bei unrelate(rel_type, A, B) werden beide Zeilen zugleich soft-gelöscht. Die Konsistenz der zwei Zeilen ist Service-Layer-Pflicht — die Datenbank erzwingt sie nicht. Speicher-Verdoppelung ist akzeptiert; Lese-Pfad-Performance hat Priorität (kein zusätzlicher View-Join).

Eindeutigkeit pro Richtung wird durch uq_entity_relation_active automatisch gewährleistet (das Partial-Unique-Tupel enthält from_entity_id/to_entity_id).

Offen

  • Selbstreferenz: gibt es Beziehungstypen, die from = to erlauben sollen? Aktuell durch Constraint ausgeschlossen.
  • Eindeutigkeit historisch: aktuell wird durch Partial Unique nur „eine aktive Beziehung gleicher Form” verhindert. Mehrfach-Aktivierung über Zeit (valid_from/valid_to ohne Soft Delete) ist nicht durch Index abgedeckt.

Verwandte Dokumente