# Zuweisungsproblem



## Kris (17. Mai 2008)

Hallo.

Es  besteht eine Verbindung zwischen Java und MySQL über Hibernate.

Vereinfacht gibt es zwei Tabellen.  Eine für Fahrten und eine für Fahrer. In der tblFahrten gibt es zwei Verknüpfungen zur tblFahrer. Einmal Fahrer und Beifahrer. Nun das Problem dies in Java umzusetzten. Ich habe ein Objekt Fahrer. Muss ich auch ein Objekt Beifahrer erstellen? 

Ich dachte jetzt daran im Objekt Fahrer mit Many to One Beziehungen ein Set fahrten und ein Set beifahrten zu erstellen. Wäre dies richtig?


----------



## Guest (18. Mai 2008)

Ja, so ungefähr
	
	
	
	





```
Fahrt
{
   ...

   @ManyToOne(optional=false) // Sonst ist es eine Geisterfahrt ;)
   @JoinColumn(name="fahrer")
   private Fahrer fahrer;

   @ManyToOne
   @JoinColumn(name="beifahrer")
   private Fahrer beifahrer;

   ...
}

Fahrer
{
   ...

   // Optional, wird evtl. für Queries benötigt.
   @OneToMany(mappedBy="fahrer", ...)
   private Set<Fahrt> fahrerFahrtSet ...   // Lustige Namen ;-)

   // Optional, wird evtl. für Queries benötigt.
   @OneToMany(mappedBy="beifahrer", ...)
   private Set<Fahrt> beifahrerFahrtSet ...

   ...
}
```


----------



## Kris (18. Mai 2008)

Danke. 
Genau so habe ich es mir gedacht.

Außer die optional = false Setzung des Fahrers. Denn die Fahrt wird erst als ein Termin eingegeben ohne Fahrerzuweisung. Hier könnte man evtl. mit Vererbungen dann arbeiten aber ich weiss nicht ob es notwendig ist. 

Dazu noch eine Frage zu Fahrer. Ich habe ein Objekt Person. (id, name, vornam, gebdat). Das Objekt Fahrer beihaltet Person.


```
public class Person extends Person
```

Es gibt auch eine Tabelle Person. Dann eine für Fahrer.

Ist das oben richtig oder sollte Person implementiert werden? Also kein Objekt sondern Interface Person erstelln.


```
public class Person implements Person
```


----------



## Guest (18. Mai 2008)

In welcher Beziehung stehen die Tabellen Person und Fahrer zueinander? OneToOne und die Attribute wie Name etc. 
sind nur in Person vorhanden? Es gibt nämlich mehrere Möglichkeiten dies abzubilden (z.B. eine Entity über zwei Tabellen,
OneToOne). Was ist in Tabelle Fahrer noch drin, dass diese überhaupt existieren muss?
Entwickelst du dein Programm zu einer bestehenden Datenbank oder liegt es daran, dass du zuerst mit ER-Model
anfängst und erst dann die passenden Entities dazu schreibst? Wenn der zweite Fall zutrifft, würde ich dir davon 
abraten. Bei JPA entwickelt man einfach objektorientiert, Persistence ergibt sich dann automatisch. (DDL kann man 
generieren lassen).


----------



## Guest (18. Mai 2008)

Übrigens, ich weiss du hast 
	
	
	
	





```
public class Fahrer extends Person
```
gemeint. Was st in Fahrer zusätzlich drin?


----------



## Kris (18. Mai 2008)

Also ich möchte schon erst in Java programmieren und auf der Basis des Programms die Datenbank erstellen. Hierzu mache ich mir erst ein Bild wie die Datenbank aussehen soll. Es handelt sich um eine OneToOne Beziehung. Fahrer hat zusätzliche Sachen wie Führerscheinklassen und das Datum ab dem er als Fahrer eingesetzt wurde. Da jede Person auch noch andere Funktionen erfüllen könnte und zum Beispiel auch in einer Tabelle Kunde vorkommen könnte. Ebenfals in OneToOne Beziehung.


----------



## Guest (18. Mai 2008)

Du kannst es wie folgt machen
	
	
	
	





```
@Entity
@Table(name="PERSON")
public class Person
{
   @Id
   @GeneratedValue
   private Long id;

   ...
}

@Entity
@SecondaryTable(name="Fahrer")
public class Fahrer extends Person
{
   @Column(table="KUNDE") // das bestimmt, in welche Tabelle das Attribut kommt
   @Temporal(TemporalType.DATE)
   private Calendar driverLicenseDate;

   ...
}

@Entity
@SecondaryTable(name="KUNDE")
public class Kunde extends Person
{
   ...
}
```
oder besser
	
	
	
	





```
@Entity
@Table(name="PERSON")
@Inheritance( strategy = InheritanceType.JOINED) // Siehe auch andere Typen
@DiscriminatorColumn( name = "TYP", discriminatorType = DiscriminatorType.STRING)
public abstract class Person
{
   @Id
   @GeneratedValue
   private Long id;

   ...
}

@Entity
@DiscriminatorValue("KUNDE")
public class Kunde extends Person
{
   @Column // Hier ist es nicht nötig die Tabelle zu benennen, das ergibt sich durch den Discriminator
   @Temporal(TemporalType.DATE)
   private Calendar dirverLicenceDate;

   ...
}

@Entity
@DiscriminatorValue("FAHRER")
public class Fahrer extends Person
{
   ...
}
```


----------



## Guest (18. Mai 2008)

Noch etwas. Das "DiscriminatorColumn" ist nur nötig, wenn du InheritanceType.SINGLE_TABLE verwendest.
Alles kommt dann in eine Tabelle und wird anhand des Discriminators unterschieden.


----------



## Guest (18. Mai 2008)

Arghh...  :autsch: Ich habe da ziemlich viele Fehler drin.  :wink: 
Hier nochmal die einfachste Variante ohne das überflüssige Lametta
	
	
	
	





```
@Entity
@Inheritance( strategy = InheritanceType.JOINED)
public abstract class Person
{
   @Id
   @GeneratedValue
   private Long id;

   ...
}

@Entity
public class Fahrer extends Person
{
   @Column
   @Temporal(TemporalType.DATE)
   private Calendar dirverLicenceDate;
   ...
}

@Entity
public class Kunde extends Person
{
   ...
}
```
Es werden drei Tabellen erzeugt. Person, Fahrer und Kunde. In Person sind die gemeinsamen Daten und
Abfragen gehen über Join.


----------



## Kris (18. Mai 2008)

Das Lametta interessiert mich aber auch.  :lol: 

Ist die Variante mit SeconderyTable richtig, wenn die Tabelle für Fahrer Driver heißen soll (z.B.) ?
Ich will auf jeden Fall die Joined und nicht die Single_Table Variante benutzen.


----------



## Guest (18. Mai 2008)

Die Version von meiner letzten Antwort ist OK, die kannst du nehmen. Es werden dabei drei Tabellen erzeugt 
und alles geht über Joins.
Das hier
	
	
	
	





```
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Person
{
   @Id
   @GeneratedValue
   private Long id;

   @Column(nullable = false)
   private String vorname;

   @Column(nullable = false)
   private String nachname;
}

@Entity
public class Kunde extends Person
{
   @Column(nullable=false)
   private String kundennummer;
}

@Entity
public class Fahrer extends Person
{
   @Column
   @Temporal(TemporalType.DATE)
   private Calendar driverLicenceDate;
}
```
wird zu folgenden DDL Statements
	
	
	
	





```
alter table Fahrer drop foreign key FK7CFB22923EEB88DB;
alter table Kunde drop foreign key FK457BBA53EEB88DB;
drop table if exists Fahrer;
drop table if exists Kunde;
drop table if exists Person;
create table Fahrer (
    id bigint not null,
    driverLicenceDate date,
    primary key (id)
) type=InnoDB;
create table Kunde (
    id bigint not null,
    kundennummer varchar(255) not null,
    primary key (id)
) type=InnoDB;
create table Person (
    id bigint not null auto_increment,
    vorname varchar(255) not null,
    nachname varchar(255) not null,
    primary key (id)
) type=InnoDB;
alter table Fahrer
    add index FK7CFB22923EEB88DB (id),
    add constraint FK7CFB22923EEB88DB
    foreign key (id)
    references Person (id);
alter table Kunde
    add index FK457BBA53EEB88DB (id),
    add constraint FK457BBA53EEB88DB
    foreign key (id)
    references Person (id);
```

Eine Query wie z.B. 
	
	
	
	





```
select k from Kunde k
```
resultiert dann in einem Inner Join mit Tabelle Person
	
	
	
	





```
select
  kunde0_.id as id1_,
  kunde0_1_.nachname as nachname1_,
  kunde0_1_.vorname as vorname1_,
  kunde0_.kundennummer as kundennu2_3_ 
 from
  Kunde kunde0_ 
 inner join
  Person kunde0_1_ 
   on kunde0_.id=kunde0_1_.id
```
Das hier
	
	
	
	





```
select p from Person p
```
wieder in einem Outer-Join über alle Tabellen der Vererbungshierarchie.
	
	
	
	





```
select
  person0_.id as id1_,
  person0_.nachname as nachname1_,
  person0_.vorname as vorname1_,
  person0_1_.driverLicenceDate as driverLi2_2_,
  person0_2_.kundennummer as kundennu2_3_,
  case 
   when person0_1_.id is not null then 1 
   when person0_2_.id is not null then 2 
   when person0_.id is not null then 0 
  end as clazz_ 
 from
  Person person0_ 
 left outer join
  Fahrer person0_1_ 
   on person0_.id=person0_1_.id 
 left outer join
  Kunde person0_2_ 
   on person0_.id=person0_2_.id
```
Mit Lametta meinte ich Annotationen wie @Table etc.  Diese sind total überflüssig, wenn du die Namen so 
behalten möchtest, wie die Klassen und Attribute heissen. Achte aber darau, dass du keine reservierten 
Wörter wie z.B. alter o.ä. verwendest.
Bei InheritanceType.JOINED sind auch keine Discriminator-Annotationen nötig, da diese nur dann benötigt 
werden, wenn alles in einer Tabelle gespeichert werden soll (InheritanceType.SINGLE_TABLE).


----------



## Kris (20. Mai 2008)

Alles klar. Vielen Dank.


----------

