Speichern einer Baumstruktur mit parent column und unique constraint

smirk_mirkin

Benutzer
Beiträge
14
Hallo,

ich möchte mit Hibernate einen Baum in eine Tabelle speichern.
Genutzt wird dazu eine Spalte parent, die den Vaterknoten speichert.
Hier das CREATE-Statement:
Code:
CREATE TABLE KATEGORIE (
    ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
    BEZEICHNUNG VARCHAR(100) NOT NULL,
    OBERKATEGORIE INTEGER NOT NULL,
    INDEX INTEGER,
    PRIMARY KEY (ID),
    CONSTRAINT uc_KATEGORIE UNIQUE (BEZEICHNUNG, OBERKATEGORIE)
);

Nun darf wegen dem unique constraint kein parent null sein, was aber bei der Wurzel der Fall ist. Erschwerend kommt hinzu, dass Hibernate automatisch aus parent einen foreign key macht, also kann ich auch nicht einfach irgendeinen parent bei der Wurzel setzen. Das Constraint brauch ich übrigens, da sonst beim zweimaligen Einlesen derselben Daten auch alles zweimal abgespeichert wird.

Wie könnte man das Dilemma am saubersten Lösen bzw. kann man vllt irgendwie Hibernate untersagen, den Fremdschlüssel auf parent zu erstellen?
 
Werbung:
Ohne mich mit DB2 jemals befasst zu haben, was wäre denn mit parent_id = id, also beides auf 1 beim Wurzeleintrag.
Also sobald der Fremdschlüssel draufliegt, was bei der Ausführung meines Hibernate-Programms passiert, geht das nicht mehr.

Davor würde es rein theoretisch gehen, aber dann müsste ich einen Datensatz manuell einfügen und das wäre doch recht unsauber. Besser wäre, den Fremdschlüssel irgendwie zu verhindern. Aber dafür kenn ich mich zu wenig mit Hibernate aus.
 
Nun man könnte auch bei der Erstellung der Tabelle schon einen Wurzeleintrag erstellen und den Fremdschlüssel erst im Anschluss. Irgendwie wird man sich behelfen müssen, aber vieleicht gibt es hier noch jemanden der sowas schonmal hatte. Dein Fall ist aber schon speziell :)
 
Nun man könnte auch bei der Erstellung der Tabelle schon einen Wurzeleintrag erstellen und den Fremdschlüssel erst im Anschluss.
Ja man könnte die Wurzel halt schon bei Createn erstellen, ist aber halt unsauber. Aber ne wirklich saubere Lösung scheint es nicht zu geben. Ich frage mich halt auch, warum bei dem unique constraint nicht wenigstens ein Wert null sein darf.

So speziell kann das Problem ja gar nicht sein, man wird ja öfters mal einen Baum mit nicht eindeutigen Namen einlesen wollen? :D Man sieht ja schon an meinem Code oben, dass es sich um einen Kategorienbaum in einem online-Shop handelt.

Mir kam auch gerade noch ne Idee:
Man könnte natürlich auch das unique constraint rausnehmen und in der Einlese-Anwendung erst mal nen fetten Select machen und den mit den einzulesenden Daten abgleichen. Und dann nur noch die inserten, die eben noch fehlen. Dann hätte man aber die Konsistenz nicht auf der Datenbank gesichert, sondern nur in der Anwendung.
 
Ja man könnte die Wurzel halt schon bei Createn erstellen, ist aber halt unsauber. Aber ne wirklich saubere Lösung scheint es nicht zu geben. Ich frage mich halt auch, warum bei dem unique constraint nicht wenigstens ein Wert null sein darf.

So speziell kann das Problem ja gar nicht sein, man wird ja öfters mal einen Baum mit nicht eindeutigen Namen einlesen wollen? :D Man sieht ja schon an meinem Code oben, dass es sich um einen Kategorienbaum in einem online-Shop handelt.

Mir kam auch gerade noch ne Idee:
Man könnte natürlich auch das unique constraint rausnehmen und in der Einlese-Anwendung erst mal nen fetten Select machen und den mit den einzulesenden Daten abgleichen. Und dann nur noch die inserten, die eben noch fehlen. Dann hätte man aber die Konsistenz nicht auf der Datenbank gesichert, sondern nur in der Anwendung.

In Deiner Tabelle sehe ich keine Spalte parent.

Code:
test=*# create table bla (id int primary key, parent int references bla, val text);
CREATE TABLE
Time: 207,389 ms
test=*# \d bla
  Table "public.bla"
 Column |  Type  | Modifiers
--------+---------+-----------
 id  | integer | not null
 parent | integer |
 val  | text  |
Indexes:
  "bla_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
  "bla_parent_fkey" FOREIGN KEY (parent) REFERENCES bla(id)
Referenced by:
  TABLE "bla" CONSTRAINT "bla_parent_fkey" FOREIGN KEY (parent) REFERENCES bla(id)

Wqarum sollte sowas wie gezeigt nicht gehen? Und warum darf ein unique nicht NULL sein?

Code:
test=*# drop table bla;
DROP TABLE
Time: 27,295 ms
test=*# create table bla(i int unique);
CREATE TABLE
Time: 5,078 ms
test=*# insert into bla values (1);
INSERT 0 1
Time: 0,444 ms
test=*# insert into bla values (null);
INSERT 0 1
Time: 0,203 ms
test=*# insert into bla values (null);
INSERT 0 1
Time: 0,194 ms
test=*# insert into bla values (null);
INSERT 0 1
Time: 0,164 ms
test=*# insert into bla values (1);
ERROR:  duplicate key value violates unique constraint "bla_i_key"
DETAIL:  Key (i)=(1) already exists.
Time: 0,351 ms

Sollte auch mit DB/Halbe gehen.
 
Werbung:
In Deiner Tabelle sehe ich keine Spalte parent.
Naja parent ist OBERKATEGORIE im Codebeispiel.

Wqarum sollte sowas wie gezeigt nicht gehen? Und warum darf ein unique nicht NULL sein?
Das was du zeigst geht, aber du hast kein unique constraint erstellt. Ich schließe per uc aus, dass ein title-parent-Paar doppelt vorkommt.
Code:
CONSTRAINT uc_KATEGORIE UNIQUE (BEZEICHNUNG, OBERKATEGORIE)
Bei DB2 müssen alle von diesem Constraint berührten
Attribute not null sein, keine Ahnung wieso.
 
Zurück
Oben