Documentation

(de:jvx:client:model:databook)

Verwendung von Master/Detail Beziehungen

Translations of this page:

Mit Master/Detail Beziehungen werden Abhängigkeiten zwischen Tabellen bzw. Daten hergestellt. Der Master kann auch als Gruppierung angesehen werden und das Detail enthält die Einzelsätze aus der Gruppe.

Kurzum werden mit Master/Detail die 1:n und n:m Beziehungen von Datenbanken aufgelöst.

Anwendungsbeispiel

Unsere Applikation verwaltet Länder, Bundesländer und Bezirke. In der Datenbank werden die Tabellen in 3. Normalform erstelle. Nachfolgend ein Auszug aus der HSQLDB:DB:

createdb.sql
CREATE TABLE COUNTRIES
(
  ID      INTEGER IDENTITY,
  COUNTRY VARCHAR(200) NOT NULL,
  EU      CHAR(1) DEFAULT 'N' NOT NULL,
  CONSTRAINT CTRY_UK UNIQUE (COUNTRY)
)
 
CREATE TABLE STATES
(
  ID      INTEGER IDENTITY,
  CTRY_ID INTEGER NOT NULL,
  STATE   VARCHAR(200) NOT NULL,
  CONSTRAINT STAT_UK UNIQUE (STATE),
  CONSTRAINT STAT_CTRY_ID_FK FOREIGN KEY (CTRY_ID) REFERENCES COUNTRIES (ID)
)
 
CREATE TABLE DISTRICTS
(
  ID       INTEGER IDENTITY,
  STAT_ID  INTEGER NOT NULL,
  DISTRICT VARCHAR(200),
  CONSTRAINT DIST_UK UNIQUE (DISTRICT),
  CONSTRAINT DIST_STAT_ID_FK FOREIGN KEY (STAT_ID) REFERENCES STATES (ID)
)

Wie anhand der Tabellendefinition zu sehen ist, sind Länder in Bundesländer eingeteilt und Bundesländer in Bezirke. In unserer Applikation erstellen wir eine Maske für die Bearbeitung der Länder, Bundesländer und Bezirke sowie deren Abhängigkeiten.

Wir erstellen zuerst unsere Server Objekte:

/**
 * Returns the countries storage.
 * 
 * @return the Countries storage
 * @throws Exception if the initialization throws an error
 */
public DBStorage getCountries() throws Exception
{
   DBStorage dbsCountries = (DBStorage)get("countries");
 
   if (dbsCountries == null)
   {
      dbsCountries = new DBStorage();
      dbsCountries.setDBAccess(getDBAccess());
      dbsCountries.setFromClause("V_COUNTRIES");
      dbsCountries.setWritebackTable("COUNTRIES");
      dbsCountries.open();
 
      put("countries", dbsCountries);
   }
 
   return dbsCountries;
}
 
/**
 * Returns the districts storage.
 * 
 * @return the Districts storage
 * @throws Exception if the initialization throws an error
 */
public DBStorage getDistricts() throws Exception
{
   DBStorage dbsDistricts = (DBStorage)get("districts");
 
   if (dbsDistricts == null)
   {
      dbsDistricts = new DBStorage();
      dbsDistricts.setDBAccess(getDBAccess());
      dbsDistricts.setFromClause("V_DISTRICTS");
      dbsDistricts.setWritebackTable("DISTRICTS");
      dbsDistricts.open();
 
      put("districts", dbsDistricts);
   }
 
   return dbsDistricts;
}
 
/**
 * Returns the states storage.
 * 
 * @return the States storage
 * @throws Exception if the initialization throws an error
 */
public DBStorage getStates() throws Exception
{
   DBStorage dbsCountries = (DBStorage)get("states");
 
   if (dbsCountries == null)
   {
      dbsCountries = new DBStorage();
      dbsCountries.setDBAccess(getDBAccess());
      dbsCountries.setFromClause("V_STATES");
      dbsCountries.setWritebackTable("STATES");
      dbsCountries.open();
 
      put("states", dbsCountries);
   }
 
   return dbsCountries;
}

Die View Definitionen für die Aufbereitung der Daten:

CREATE VIEW V_COUNTRIES AS
SELECT c.ID
      ,c.COUNTRY
      ,c.EU
  FROM COUNTRIES c
 ORDER BY c.COUNTRY
 
CREATE VIEW V_STATES AS
SELECT s.ID
      ,s.CTRY_ID
      ,s.STATE
  FROM STATES s
 ORDER BY s.STATE
 
CREATE VIEW V_DISTRICTS AS
SELECT d.ID
      ,d.STAT_ID
      ,d.DISTRICT
  FROM DISTRICTS d
 ORDER BY d.DISTRICT

In unserer Maske müssen wir nun die Verbindung zu den Server Objekten herstellen und die Master/Detail Beziehungen definieren:

rdbCountries.setDataSource(dataSource);
rdbCountries.setName("countries");
rdbCountries.open();
 
rdbStates.setDataSource(dataSource);
rdbStates.setName("states");
rdbStates.setMasterReference(new ReferenceDefinition(new String[] {"CTRY_ID"}, 
                                 rdbCountries, new String[] {"ID"}));
rdbStates.open();
 
rdbDistricts.setDataSource(dataSource);
rdbDistricts.setName("districts");
rdbDistricts.setMasterReference(new ReferenceDefinition(new String[] {"STAT_ID"}, 
                                    rdbStates, new String[] {"ID"}));
rdbDistricts.open();

Eine Master/Detail Beziehung wird beispielsweise hergestellt mit:

rdbDistricts.setMasterReference(new ReferenceDefinition(new String[] {"STAT_ID"}, 
                                    rdbStates, new String[] {"ID"}));

Die Master/Detail Beziehung zwischen Bundesländern und Ländern wird über den Fremdschlüssel (STATES.CTRY_ID) zum Primärschlüssel (COUNTRIES.ID) hergestellt. Das bedeutet daß bei der Selektion eines Landes alle Bundesländer angezeigt werden. Sämtliche Bundesländer die nicht dem gewählten “Master” Land zugeordnet wurden, werden nicht angezeigt.

Wenn ein neues Bundesland eingegeben wird, wird automatisch der richtige Fremdschlüssel verwendet. Das Bundesland wird somit automatisch dem richtigen Land zugeordnet.

Die Master/Detail Beziehung zwischen Bezirken und Bundesländern wird über den Fremdschlüssel (DISTRICTS.STAT_ID) zum Primärschüssel (STATES.ID) hergestellt. Das bedeutet daß bei der Selektion eines Bundeslandes alle Bezirke angezeigt werden. Sämtliche Bezirke die nicht dem gewählten “Master” Bundesland zugeordnet wurden, werden nicht angezeigt.

Wenn ein neuer Bezirk eingegeben wird, wird automatisch das richtige Bundesland verwendet. Der Bezirk wird somit automatisch dem richtigen Bundesland zugeordnet.


Hinweis

Eine Master/Detail Beziehung setzt NICHT voraus das eine Fremdschlüsselbeziehung zwischen zwei Tabellen besteht. Es können beliebige Spalten verwendet werden.

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information