JPA Annotations @JoinTable oder eigenes Mapping

Status
Nicht offen für weitere Antworten.

mephi

Bekanntes Mitglied
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

Top Contributor
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

Bekanntes Mitglied
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.
 

byte

Top Contributor
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. :)
 
M

maki

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

mephi

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

Code:
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:

Code:
@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

Bekanntes Mitglied
hier noch ein paar methoden wie ich mein PK setze:

Code:
	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:


Code:
	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

Bekanntes Mitglied
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

Bekanntes Mitglied
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.

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

Hier das Feld in CustomSequence

Code:
	@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 ...
Code:
 NULL        NULL     0           1 Dummy     NULL
 
G

Guest

Gast
Was soll dieser Integer in dem Map sein?

Siehe auch: @MapKey Annotation.
 

mephi

Bekanntes Mitglied
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?
 
G

Guest

Gast
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.
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen


Oben