Ein Stackoverflow-Mapping (Ruhezustand)
Frage
Nehmen wir eine Abbildung wie diese
@Entity
public class User {
private Integer id
private List<Info> infoList;
@Id
public getId() {
return this.id;
}
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="USER_ID", insertable=false, updateable=false, nullable=false)
public getInfoList() {
return this.infoList;
}
public void addQuestion(Info question) {
info.setInfoCategory(InfoCategory.QUESTION);
info.setInfoId(new InfoId(getId(), getInfoList().size()));
getInfoList().add(question);
}
public void addAnswer(InfoRepository repository, Integer questionIndex, Info answer) {
Info question = repository.getInfoById(new InfoId(getId(), questionIndex));
if(question.getInfoCategory().equals(InfoCategory.ANSWER))
throw new RuntimeException("Is not a question");
if(question.getAnswer() != null)
throw new RuntimeException("You can not post a new answer");
answer.setInfoCategory(InfoCategory.ANSWER);
answer.setInfoId(new InfoId(getId(), getInfoList().size()));
getInfoList().add(answer);
question.setAnswer(answer);
}
}
Und eine Frage und Antwort durch eine Info-Klasse zugeordnet
@Entity
public class Info implements Serializable {
private InfoId infoId;
private Info answer;
private InfoCategory infoCategory;
public Info() {}
@Embeddable
public static class InfoId {
private Integer userId;
private Integer index;
public InfoId(Integer userId, Integer index) {
this.userId = userId;
this.index = index;
}
@Column("USER_ID", updateable=false, nullable=false)
public getUserId() {
return this.userId;
}
@Column("INFO_INDEX", updateable=false, nullable=false)
public getIndex() {
return this.index;
}
// equals and hashcode
}
// mapped as a ManyToOne instead of @OneToOne
@ManyToOne
JoinColumns({
JoinColumn(name="USER_ID", referencedColumnName="USER_ID", insertable=false, updateable=false),
JoinColumn(name="ANSWER_INDEX", referencedColumnName="INFO_INDEX", insertable=false)
})
public Info getAnswer() {
return this.answer;
}
@EmbeddedId
public InfoId getInfoId() {
return this.infoId;
}
}
In getAnswer verwenden i ManyToOne statt OneToOne, weil einige Fragen im Zusammenhang mit OneToOne Kartographie. Ein OneToOne kann als ManyToOne (unique = true in @JoinColumn) abgebildet werden. INFO_INDEX ist nicht auf einen bestimmten Zweck verwendet. Nur ein Schlüssel, um eine Verbindung unterstützt Primärschlüssel in einem Altsystem.
Vor der Beantwortung, kümmern sich um die folgenden:
Wenn ein Objekt eine zugewiesene Kennung hat, oder einen zusammengesetzten Schlüssel, sollte die Kennung an die Objektinstanz zugeordnet wird vor dem Aufruf von save ()
Also ich habe zur Karte JoinColumn (name = "BENUTZER_ID", referencedColumnName = "BENUTZER_ID", einführbar = false, aktualisierbare = false) in getAnswer weil Hibernate nicht zwei erlaubt veränderbare Eigenschaften die gleichen teilen collumn (userId auch BENUTZER_ID verwendet) sonst i BENUTZER_ID in Antwort Eigenschaft erhalten werden muss einführbar abgebildet werden = false, aktualisierbare = false
Jetzt einen Blick auf getAnswer Mapping nehmen
@ManyToOne
JoinColumns({
JoinColumn(name="USER_ID", referencedColumnName="USER_ID", insertable=false, updateable=false),
JoinColumn(name="ANSWER_INDEX", referencedColumnName="INFO_INDEX", insertable=false)
})
Weil es, Hibernate klagt man nicht anders einsetzbar mischen und aktualisierbar
Was soll ich tun, um es zu übergeben?
Achten Sie darauf, es ist ein Altsystem.
Grüße,
Lösung 2
Nach Frage in getAnswer Mapping
@ManyToOne
JoinColumns({
JoinColumn(name="USER_ID", referencedColumnName="USER_ID", insertable=false, updateable=false),
JoinColumn(name="ANSWER_INDEX", referencedColumnName="INFO_INDEX", insertable=false)
})
Ruhezustand wird sich beschweren, weil es mischen sich erlaubt nicht anders einsetzbar und aktualisierbar. Beachten Sie ein einsetzbar und aktualisierbar in BENUTZER_ID JoinColumn und nur einsetzbar in ANSWER_INDEX JoinColumn.
Also, um es zu passieren, i einrichten ANSWER_INDEX JoinCollumn accortding zu
JoinColumn(name="ANSWER_INDEX", referencedColumnName="INFO_INDEX", insertable=false, updateable=false)
Auf diese Weise Hibernate nicht beschweren.
Und ich gründe eine neue Eigenschaft namens answerIndex
private Integer answerIndex;
@Column(name="ANSWER_INDEX", insertable=false)
public void getAnswerIndex() {
return this.answerIndex;
}
Dann in Benutzer addAnswer
public void addAnswer(InfoRepository repository, Integer questionIndex, Info answer) {
Info question = repository.getInfoById(new InfoId(getId(), questionIndex));
if(question.getInfoCategory().equals(InfoCategory.ANSWER))
throw new RuntimeException("Is not a question");
if(question.getAnswer() != null)
throw new RuntimeException("You can not post a new answer");
answer.setInfoCategory(InfoCategory.ANSWER);
answer.setInfoId(new InfoId(getId(), getInfoList().size()));
getInfoList().add(answer);
// Added in order to set up AnswerIndex property
question.setAnswerIndex(answer.getInfoId().getIndex());
}
Andere Tipps
Sie würde drastisch vereinfacht Ihr Mapping durch eingebettete ID verzichten und ein Surrogat PK stattdessen verwenden.
Wenn Sie InfoId.index
für einen bestimmten Zweck verwenden müssen (Fragen / Antworten bestellen? Sie, dass in list
Mapping angeben), halten Sie es als eine regelmäßige Eigenschaft.
UserId
wird durch ManyToOne
auf User
ersetzt werden; die anderen Assoziationsende (in User
Klasse) als @OneToMany(mappedBy="User")
abgebildet werden
Warum ist Antwort als ManyToOne
abgebildet? Sollte es nicht OneToMany
(zum Beispiel 1 Frage viele Antworten) werden? So oder so, Mapping-Klasse auf sich selbst ist weniger als ideal - Sie sind im Grunde eine „Adjazenzliste“ Modellhierarchie Implementierung, die ineffizient ist; und in Ihrem Fall müssen Sie sicherstellen, dass es nicht mehr als 2 Ebenen. Ich würde Question
und Answer
als separate Klassen zuordnen; Sie können sie eine gemeinsame Schnittstelle haben implementieren oder die gleiche Basis (möglicherweise abstrakte) Klasse erweitern; In beiden Fällen können Sie impliziten Polymorphismus von Hibernate zur Verfügung gestellt genießen.