# JPA Annotations @JoinTable oder eigenes Mapping



## mephi (17. Dez 2008)

Hi,

mal wieder eine Frage zu JPA 
Ist es möglich bei einer ManyToMany Beziehung irgendwie noch Zusatzinformationen in die Relation zu bekommen, z.B. zwischen Student und Vorlesung noch eine Note. Oder muss ich mir eine eigene Klasse fürs Mapping schreiben und mit @EmbeddedId die beiden FKs als PK umsetzen und dann in dieser Klasse die Info speichern?


----------



## byte (17. Dez 2008)

Ausser ner IndexColumn fällt mir nix ein, was man direkt in einem (automatisch generierten) @JoinTable noch unterbringen könnte.

Aber ich frage mich auch, warum man sowas tun sollte? Du arbeitest später mit den POJOs, also gehört die Note auch in ein POJO.


----------



## mephi (17. Dez 2008)

Wollte nur sicher gehn, bevor ich wieder soviel ändere und es vll eine einfachere Möglichkeit gäbe. Ich würd mich nicht als so fit in JPA bezeichnen, dass ich das mal eben so kurz ändere.


----------



## maki (17. Dez 2008)

> Wollte nur sicher gehn, bevor ich wieder soviel ändere


Änderungen sind fast das ganze Leben... gehört zum Job.


----------



## byte (17. Dez 2008)

Ich habe JPA auf diese Weise gelernt. Das Datenmodell wurde in der Entwurfsphase ständig refactored und ich war immer wieder damit beschäftigt, das Mapping anzupassen.


----------



## maki (17. Dez 2008)

MIt Annos viel einfacher als mit XML Mapping, wie du ja schon im anderen Thread erwähnt hattest byto


----------



## mephi (17. Dez 2008)

Ok nun hab ich das erste Problem. Ich bekomm für die Exception


```
Caused by: java.lang.ClassCastException: system.impl.CustomSequenceImpl$CustomSequencePK incompatible with java.lang.Integer
```

und kann mir nicht erklären woher die kommt. Könnt ihr mir da helfen?

meine klasse:


```
@Entity
@Table(name="customsequence")
public class CustomSequenceImpl implements ICustomSequence{
	
	
	@Embeddable
	public static class CustomSequencePK implements Serializable{
		
		@ManyToOne(targetEntity=SequenceImpl.class)
		@JoinColumn(nullable=false)
		private ISequence sequence;
		@ManyToOne(targetEntity=UserImpl.class)
		@JoinColumn(nullable=false)
		private IUser user;

		public CustomSequencePK(){
  
		}  
		
	    public IUser getUser() {
	        return this.user;
	    }

	    public void setUser(IUser user) {
	        this.user = user;
	    }

	    public ISequence getSequence() {
	        return this.sequence;
	    }

	    public void setId(ISequence sequence) {
	        this.sequence = sequence;
	    }

	    public int hashCode() {
	        return (int) this.user.getId().hashCode() + this.sequence.getId();
	    }

	    public boolean equals(Object obj) {
	        if (obj == this) return true;
	        if (obj == null) return false;
	        if (!(obj instanceof CustomSequencePK)) return false;
	        CustomSequencePK pk = (CustomSequencePK) obj;
	        return pk.sequence.getId() == this.sequence.getId() && pk.user.getId().equals(this.user.getId());
	    }

	}
	   
	@EmbeddedId
	private CustomSequencePK pk;
```


----------



## mephi (18. Dez 2008)

hier noch ein paar methoden wie ich mein PK setze:


```
public ISequence getSequence() {
		return this.pk.getSequence();
	}

	public IUser getUser() {
		return this.pk.getUser();
	}

	public void setSequence(ISequence sequence) {
		this.pk.setSequence(sequence);
		
	}

	public void setUser(IUser user) {
		this.pk.setUser(user);
	}
```


*edit*

das hier könnte nicht interessant sein. so lad ich die sequenz:



```
public ICustomSequence loadCustomSequence(int seqId, IUser user) {
		ISequence sequence = (ISequence)this.loadSequence(seqId);
		CustomSequencePK customSeqPk = new CustomSequenceImpl.CustomSequencePK();
		customSeqPk.setSequence(sequence);
		customSeqPk.setUser(user);
		ICustomSequence customSequence = (ICustomSequence)this.getEntityManager().find(CustomSequenceImpl.class, customSeqPk);
		if (customSequence == null) {
			customSequence = new CustomSequenceImpl();
			customSequence.setUser(user);
			customSequence.setSequence(sequence);
			this.getEntityManager().persist(customSequence);
		}
		return customSequence;
	}
```


----------



## mephi (18. Dez 2008)

O, ich weiß nun wo das Problem ist. Ich habe mit User und CustomSequence eine bidirektionale Beziehung. Ich hatte bisher in User eine Map mit @ManyToMany Integer als key(für die reihenfolge) und sequence als value.
jetzt habe ich eine Map mit @OneToMany, mappedBy="primaryKey.User" auch mit Integer als key für die reihenfolge und der customSequence als value. aber das scheint nicht ganz hinzuhauen.. ohne das mappedBy kommt der fehler von oben und mit dem mappedBy legt der in customsequence ein feld an namens mapKey dass seltsamerweise auch noch null ist...


----------



## mephi (19. Dez 2008)

Ich bin echt am verzweifeln. Ich komm mir vor als wäre ich in einem Urwald voller Exceptions durch die ich mich hindurchkämpfe und dabei nichtmal weiß ob ich überhaupt in die richtige Richtung laufe..

Ich hänge immernoch an meinem POJO, dass die Relation übernimmt. Nur bin ich nun von @EmbeddidId auf @IdClass umgestiegen.
Wenn ich es anlege und persistiere klappt es wunderbar. Aber beim laden geht etwas schief. Hab mir die CustomSequence Table angeschaut und gesehen, dass es da ein "mapkey" gibt der NULL ist. Das ist die CustomSequenceMap vom User.


```
@OneToMany(targetEntity=CustomSequenceImpl.class, fetch=FetchType.LAZY , mappedBy="user")
	private Map<Integer, ICustomSequence> sequenceList = new HashMap<Integer, ICustomSequence>();
```

Hier das Feld in CustomSequence


```
@Id
	@ManyToOne
	private IUser user;
```

Die IdClass sieht eigentlich aus wie die EmbeddedId oben, nur dass die Klasse nicht mehr als Innere Klasse definiert ist sondern als eigenständige.

1 ist die sequence und Dummy ist der User.. und dann hinten MapKey NULL ...

```
NULL        NULL     0           1 Dummy     NULL
```


----------



## mephi (26. Dez 2008)

hm gibts doch net, dass dieses problem sich net lösen lässt


----------



## Guest (26. Dez 2008)

Was soll dieser Integer in dem Map sein? 

Siehe auch: @MapKey Annotation.


----------



## mephi (27. Dez 2008)

naja, der key von der hashmap. bestimmte die reihenfolge, fand ich am einfachsten um auch die reihenfolge ändern zu können.
bisher hat das mit dem mapkey auch immer funktioniert ohne dass ich was machen musste. nur in diesem fall nicht. ob das an der @IdClass liegt?


----------



## Guest (29. Dez 2008)

Dir ist aber klar, dass HashMap keine Reihenfolge der Keys garantiert?

Der Key in dem Map muss ein Feld/Attribut der Klasse CusomSequenceImpl sein, deswegen die MapKey Annotation.
Wenn du einfach nur sicherstellen möchtest, dass die Reihenfolge stimmt, kannst du auch @OrderBy("attributname") 
verwenden und dann aber einen Collection-Typen, der sortierbar ist.


----------

