# Hibernate ManyToMany zusammengesetzter Primärschlüssel, problem.



## casi91 (15. Jun 2012)

Hallo Community.
Ich habe mal wieder ein Problem mit Hibernate und hoffe auf Hilfe 

Folgendes Konstrukt:
Tabelle: Adressliste (ID(PK), Bezeichnung)
Tabelle: FilialKontakt (FilialID(PK/FK), KontaktID(PK/FK), primaerKZ)

Nun kann eine Adressliste einen oder mehrere Filialkontakte haben 
und ein Filialkontakt kann in einer oder mehreren Adresslisten vorhanden sein.

==>Tabelle: FilialKontaktAdressliste(FilialID(PK/FK), KontaktID(PK/FK), AdresslisteID(PK/FK))

Ich weiß nun nicht, wie mein Annotaition auszusehen hat 
Problem bereitet mir hierbei der zusammengesetzte Primärschlüssel.


Bei einem solchen Konstrukt:
Tabelle: Filiale(ID, Name)
Tabelle: Branche(ID, Name)

kann eine Filiale eine oder mehrere Branchen haben
und eine Branche kann einer oder mehreren Filialen zugeordnet sein

==> Tabelle FilialBranche(FilialID(PK/FK), BrancheID(PK/FK))

Sieht mein Annotation (in der Filiale.java) folgendermaßen aus:

```
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
	@JoinTable(name="FILIALBRANCHE", joinColumns = {
				@JoinColumn(name="FILIALID") }, inverseJoinColumns = {
				@JoinColumn(name="BRANCHEID") } )
	private Set <Branche> myBranche = new HashSet<Branche>(0);
```
und das funktionier auch wunderbar.

Wie erwähnt, ist mein Problem das obere Konstrukt und dabei der zusammengesetzte Primärschlüssel.
Habe dazu leider noch nichts brauchbares gefunden.
Hoffe mein Problem ist deutlich geworden und mir kann jemand helfen 

Danke schonmal im vorraus.


----------



## casi91 (18. Jun 2012)

keiner eine Idee?
Ich weiß nun schonmal, dass ich anscheinden meinen zusammengesetzten Schlüssel in eine neue Klasse auslagern muss. Welche dann mit @Embeddable beschrieben wird.

Aber mehr hab ich leider noch nicht.
Irgendwie werde ich aus den gefundenen Beispiele nicht schlau :-(

hier mal noch meine Klassen zu Filialkontakt und Adressliste:

```
@Entity
@Table(name="FILIALKONTAKT")
public class FilialKontakt implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -3669314898011844021L;

	@Id
	@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.PERSIST)
	@JoinColumn(name = "FILIALID", insertable=true, updatable=true)		
	private Filiale myFiliale;
	
	@Id
	@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.PERSIST)
	@JoinColumn(name = "KONTAKTID", insertable=true, updatable=true)	
	private Kontakte myKontakt;	
	
	@Column
	private Integer primaerKz;
	
	public FilialKontakt() {
		
	}
//nachfolgend getter und setter
```


```
@Entity
@Table(name="ADRESSLISTE")
public class Adressliste {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) 
	@Column(name = "ADRESSLISTEID")		
	private Integer adresslisteid;
	
	@Column(name="BEZEICHNUNG")
	private String  bezeichnung;
	
	public Adressliste() {
		
	}
//nachfolgend getter und setter
```


----------



## casi91 (20. Jun 2012)

So,
ich bin jetzt soweit, dass ich weiß, dass ich für einen zusammengesetzen Primärschlüssel eine extra Klasse benötige.
In der Klasse muss ich dann die Primärschlüssel zusammenfassen und in meiner eigentlichen Datenbankklasse einbinden.
Beispiel:


```
@Table(name="FILIALSTATUS")
public class FilialStatus implements Serializable {

	@Id
	public FilialStatusPK pk;

	@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.PERSIST)
	@JoinColumn(name = "UNTERSTATUSID", insertable=true, updatable=true)			
	private Unterstatus myUnterStatus;
	
	@ManyToOne(fetch=FetchType.EAGER,cascade = CascadeType.PERSIST)
	@JoinColumn(name = "FILIALID", insertable=true, updatable=true)
	private Filiale myFiliale;

....
}
```

und die Primärschlüsselklasse:

```
@Embeddable
public class FilialStatusPK implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 8667250496344372556L;
	private Integer FilialID;
	private Integer UnterstatusID;
	
	public Integer getFilialID() {
		return FilialID;
	}
	public void setFilialID(Integer filialID) {
		FilialID = filialID;
	}
	
	public Integer getUnterstatusID() {
		return UnterstatusID;
	}
	public void setUnterstatusID(Integer unterstatusID) {
		UnterstatusID = unterstatusID;
	}
	
}
```

eingebunden wird das ganze dann folgendermaßen (hier in der Klasse "Filiale.java")

```
...
	@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.PERSIST)
	@JoinColumn(name="FILIALID", referencedColumnName="FilialID")
	private Set <FilialStatus> filialstatus = new HashSet<FilialStatus>();	
...
```

Das funktioniert auch nun schonmal wunderbar.
Jetzt muss ich das ganze nur noch für das von mir beschriebene Konstrukt hinbekommen:
Tabelle: Adressliste (ID(PK), Bezeichnung)
Tabelle: FilialKontakt (FilialID(PK/FK), KontaktID(PK/FK), primaerKZ)
==>Tabelle: FilialKontaktAdressliste(FilialID(PK/FK), KontaktID(PK/FK), AdresslisteID(PK/FK))

Hier habe ich schon angefangen, aber leider funktioniert es noch nicht.
Hier meine bisheriger Versuch:

```
@Entity
@Table(name="KONTAKTADRESSLISTE")
public class KontaktAdressliste implements Serializable {
	@Id
	public KontaktAdresslistePK pk;
	
	@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
	@JoinColumn(name ="ADRESSLISTEID", insertable=true, updatable=true)
	private Adressliste myAdressliste;
	
	@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
	@JoinColumns({
		@JoinColumn(name="FILIALID", referencedColumnName="FilialID"),    
	    @JoinColumn(name="KONTAKTID", referencedColumnName="KontaktID")
	})
	private Set<FilialKontakt> myFilialKontakt;


	public Set<FilialKontakt> getMyFilialKontakt() {
		return myFilialKontakt;
	}

	public void setMyFilialKontakt(Set<FilialKontakt> myFilialKontakt) {
		this.myFilialKontakt = myFilialKontakt;
	}

	public Adressliste getMyAdressliste() {
		return myAdressliste;
	}

	public void setMyAdressliste(Adressliste myAdressliste) {
		this.myAdressliste = myAdressliste;
	}
}
```


```
@Embeddable
public class KontaktAdresslistePK implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -7201017366522104402L;
	private Integer AdresslisteID;
	private Integer FilialID;
	private Integer KontaktID;
	
	public Integer getAdresslisteID() {
		return AdresslisteID;
	}
	public void setAdresslisteID(Integer adresslisteID) {
		AdresslisteID = adresslisteID;
	}
	
	public Integer getFilialID() {
		return FilialID;
	}
	public void setFilialID(Integer filialID) {
		FilialID = filialID;
	}
	
	public Integer getKontaktID() {
		return KontaktID;
	}
	public void setKontaktID(Integer kontaktID) {
		KontaktID = kontaktID;
	}
	
}
```


Hat vielleicht jemand aufgrund dieser Angaben eine Idee, was hier noch mein Fehler sein könnte?
Bin für jede Hilfe dankbar


----------



## typhusa (21. Jun 2012)

Hallo,

also zusammengesetzte Primärschlüssel kannst Du in Hibernate über Composite-Keys abdecken. Ich hab das zwar noch nie mit Hibernate/Java gemacht, sondern nur mit NHibernate (das ist der C#-Clon von Hibernate), aber vielleicht hilft Dir das ja weiter:

```
[Set(Table = "abk_has_land", BatchSize = 50)]
        [Cache(1, Usage = CacheUsage.ReadWrite)]
        [Key(2)]
        [Column(3, Name="abk_id")]
        [Column(4, Name = "abk_version")]
        [Column(5, Name = "abk_baureihe_id")]
        [ManyToMany(6, ClassType = typeof(Land), Column = "land_id")]
        virtual public ICollection<Land> Laender { get; set; }
```

Ein kurzes Googlen zu einem Many-To-Many-Mapping mit Composite-Keys in Hibernate liefert jedenfalls tausende Ergebnisse, schau da am besten nochmal nach.

Gruß,
Typhusa


----------

