Hallo!
Ich habe ein JPA-Problem mit mehreren one-to-many-Beziehungen. Es geht dabei um folgendes Szenario:
Wir haben einen Garten. In diesem Garten gibt es mehrere Pflanzen, z.B. Blumen und Bäume. Blumen und Bäume leiten von der gemeinsamen Basisklasse Pflanzen ab. Sowohl Blumen als auch Bäume eines Gartens können abgefragt werden. (Ja ja... ich bin auch kein wirklicher Pflanzen-Fan, jedoch habe ich dieses Beispiel aus einem Buch, welches bei mir einfach nicht funktioniert!)
Meine Lösung schaut momentan so aus:
Die Entitäten sehen (grob) folgendermaßen aus:
@Entity
@Table(name = "GARDEN_TABLE")
GardenEntity {
@Id
public Long id;
@Column(nullable = false)
public String name;
@OneToMany(mappedBy = "garden", cascade = CascadeType.ALL)
public List<TreeEntity> trees = new ArrayList<TreeEntity>();
@OneToMany(mappedBy = "garden", cascade = CascadeType.ALL)
public List<FlowerEntity> flowers = new ArrayList<FlowerEntity>();
public GardenEntity(String name) {
this.name = name();
}
}
@Entity
@Table(name = "PLANT_TABLE")
@DiscriminatorColumn(name = "DTYPE", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
PlantEntity {
@Id
public Long id;
@Column(nullable = false)
public String name;
@ManyToOne
@JoinColumn(name = "GARDEN_FK", nullable = false)
public GardenEntity garden; // important: backref to containing garden
public PlantEntity(String name, GardenEntity garden) {
this.name = name;
this.garden = garden;
}
}
@Entity
@DiscriminatorValue(value = "FLOWER")
FlowerEntity extends PlantEntity {
public String color;
public FlowerEntity(String name, GardenEntity garden) {
super(name, garden);
}
}
@Entity
@DiscriminatorValue(value = "TREE")
TreeEntity extends PlantEntity {
public boolean fruits;
public TreeEntity(String name, GardenEntity garden) {
super(name, garden);
}
}
Wichtig ist die Backref von Pflanze zu Garten, wir haben also eine birektionale Beziehung.
Die Tabellen werden folgendermaßen erstellt:
--Drop Table GARDEN_TABLE;
Create Table GARDEN_TABLE(
ID BIGINT NOT NULL,
NAME VARCHAR(8000),
primary key (ID))
;
--Drop Table PLANT_TABLE;
Create Table PLANT_TABLE(
ID BIGINT NOT NULL,
GARDEN_FK BIGINT NOT NULL,
DTYPE VARCHAR(32) NOT NULL,
NAME VARCHAR(8000),
COLOR VARCHAR(8000),
FRUITS SMALLINT,
primary key (ID))
;
-- constraint between PlantEntity.garden and GardenEntity
--alter table PLANT_TABLE drop constraint PLANT_TABLE_C01;
alter table PLANT_TABLE
add constraint PLANT_TABLE_C01
foreign key (GARDEN_FK)
references GARDEN_TABLE (ID)
On Delete Restrict
On Update No Action
;
-- index for foreign key attribute PlantEntity.garden
create Index PLANT_TABLE_F1
on PLANT_TABLE
(GARDEN_FK)
;
Das Problem äußert sich Folgendermaßen:
Wenn ich das ganze ausprobiere, scheint alles schön zu funktionieren. Folgender Use-Case schlägt jedoch fehl:
1.) Lade einen Garten, der bereits Blumen und Bäume hat -> OK
2.) Greife auf die Blumen zu -> NOK: In der Collection der Blumen sind auch die Bäume enthalten!
Kann mir irgendjemand weiterhelfen??
Vielen Dank
dubdidub
Ich habe ein JPA-Problem mit mehreren one-to-many-Beziehungen. Es geht dabei um folgendes Szenario:
Wir haben einen Garten. In diesem Garten gibt es mehrere Pflanzen, z.B. Blumen und Bäume. Blumen und Bäume leiten von der gemeinsamen Basisklasse Pflanzen ab. Sowohl Blumen als auch Bäume eines Gartens können abgefragt werden. (Ja ja... ich bin auch kein wirklicher Pflanzen-Fan, jedoch habe ich dieses Beispiel aus einem Buch, welches bei mir einfach nicht funktioniert!)
Meine Lösung schaut momentan so aus:
Die Entitäten sehen (grob) folgendermaßen aus:
@Entity
@Table(name = "GARDEN_TABLE")
GardenEntity {
@Id
public Long id;
@Column(nullable = false)
public String name;
@OneToMany(mappedBy = "garden", cascade = CascadeType.ALL)
public List<TreeEntity> trees = new ArrayList<TreeEntity>();
@OneToMany(mappedBy = "garden", cascade = CascadeType.ALL)
public List<FlowerEntity> flowers = new ArrayList<FlowerEntity>();
public GardenEntity(String name) {
this.name = name();
}
}
@Entity
@Table(name = "PLANT_TABLE")
@DiscriminatorColumn(name = "DTYPE", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
PlantEntity {
@Id
public Long id;
@Column(nullable = false)
public String name;
@ManyToOne
@JoinColumn(name = "GARDEN_FK", nullable = false)
public GardenEntity garden; // important: backref to containing garden
public PlantEntity(String name, GardenEntity garden) {
this.name = name;
this.garden = garden;
}
}
@Entity
@DiscriminatorValue(value = "FLOWER")
FlowerEntity extends PlantEntity {
public String color;
public FlowerEntity(String name, GardenEntity garden) {
super(name, garden);
}
}
@Entity
@DiscriminatorValue(value = "TREE")
TreeEntity extends PlantEntity {
public boolean fruits;
public TreeEntity(String name, GardenEntity garden) {
super(name, garden);
}
}
Wichtig ist die Backref von Pflanze zu Garten, wir haben also eine birektionale Beziehung.
Die Tabellen werden folgendermaßen erstellt:
--Drop Table GARDEN_TABLE;
Create Table GARDEN_TABLE(
ID BIGINT NOT NULL,
NAME VARCHAR(8000),
primary key (ID))
;
--Drop Table PLANT_TABLE;
Create Table PLANT_TABLE(
ID BIGINT NOT NULL,
GARDEN_FK BIGINT NOT NULL,
DTYPE VARCHAR(32) NOT NULL,
NAME VARCHAR(8000),
COLOR VARCHAR(8000),
FRUITS SMALLINT,
primary key (ID))
;
-- constraint between PlantEntity.garden and GardenEntity
--alter table PLANT_TABLE drop constraint PLANT_TABLE_C01;
alter table PLANT_TABLE
add constraint PLANT_TABLE_C01
foreign key (GARDEN_FK)
references GARDEN_TABLE (ID)
On Delete Restrict
On Update No Action
;
-- index for foreign key attribute PlantEntity.garden
create Index PLANT_TABLE_F1
on PLANT_TABLE
(GARDEN_FK)
;
Das Problem äußert sich Folgendermaßen:
Wenn ich das ganze ausprobiere, scheint alles schön zu funktionieren. Folgender Use-Case schlägt jedoch fehl:
1.) Lade einen Garten, der bereits Blumen und Bäume hat -> OK
2.) Greife auf die Blumen zu -> NOK: In der Collection der Blumen sind auch die Bäume enthalten!
Kann mir irgendjemand weiterhelfen??
Vielen Dank
dubdidub
Comment