【发布时间】:2010-11-27 08:39:21
【问题描述】:
假设一个像这样的映射
@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);
}
}
以及由 Info 类映射的问答
@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;
}
}
在 getAnswer 中,我使用 ManyToOne 而不是 OneToOne,因为一些问题与 OneToOne 映射有关。 OneToOne 可以映射为 ManyToOne(@JoinColumn 中的 unique=true)。 INFO_INDEX 与任何特定目的无关。只需一个键即可支持 LEGACY 系统中的复合主键。
在回答之前,请注意以下事项:
如果一个对象有一个分配的标识符,或者一个复合键,在调用 save() 之前,标识符应该分配给对象实例
所以我必须在 getAnswer 中映射 JoinColumn(name="USER_ID", referencedColumnName="USER_ID", insertable=false, updateable=false) 因为 Hibernate 不允许两个可变属性共享相同collumn (userId 也使用 USER_ID) 否则我将在 answer 属性中获取 USER_ID 必须使用 insertable=false, updateable=false 进行映射
现在看看 getAnswer 映射
@ManyToOne
JoinColumns({
JoinColumn(name="USER_ID", referencedColumnName="USER_ID", insertable=false, updateable=false),
JoinColumn(name="ANSWER_INDEX", referencedColumnName="INFO_INDEX", insertable=false)
})
因为它,Hibernate 抱怨你不能混合不同的可插入和可更新
我应该怎么做才能通过它?
请注意它是一个遗留系统。
问候,
【问题讨论】:
标签: java hibernate mapping orm