Verwendung von Master/Detail Beziehungen

Dokumente für die Entwicklung von und mit JVx

Verwendung von Master/Detail Beziehungen

Postby Development@SIB » Tue Sep 29, 2009 4:03 pm

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, Staaten und Bezirke. In der Datenbank werden die Tabellen in 3. Normalform erstelle. Nachfolgend ein Auszug aus der HSQLDB:

Code: Select all
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 Staaten eingeteilt und Staaten in Bezirke. In unserer Applikation erstellen wir eine Maske für die Bearbeitung der Länder, Staaten und Bezirke sowie deren Abhängigkeiten.

Wir erstellen zuerst unsere Server Objekte:

Code: Select all
/**
* 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:

Code: Select all
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:

Code: Select all
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 z.B. mit:

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

hergestellt.

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

Wenn ein neuer Staat eingegeben wird, wird automatisch der richtige Fremdschlüssel verwendet. Der Staat wird somit automatisch dem richtigen Land zugeordnet.

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

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


Hinweise

Eine Master/Detail Beziehung setzt NICHT voraus das eine Fremdschlüsselbeziehung zwischen zwei Tabellen besteht. Es können beliebige Spalten verwendet werden.
Development@SIB
 
Posts: 58
Joined: Mon Sep 28, 2009 1:54 pm

Return to Dokumentation