2009-09-11 57 views
3

假設這樣一個出現StackOverflow映射(休眠)

@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); 
    } 

} 

查勘和問題,回答一個信息類

@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映射我使用的,而不是OneToOne多對一,因爲一些問題與OneToOne映射相關。 OneToOne可以映射爲ManyToOne(@JoinColumn中的unique = true)。 INFO_INDEX與任何特定用途無關。只是爲了在LEGACY系統中支持複合主鍵的一個關鍵。

應答之前,照顧以下的:

如果一個對象具有分配的標識符,或複合密鑰,標識符應當被分配給該對象實例之前調用save()

因此,我必須映射JoinAnswer中的JoinColumn(name =「USER_ID」,referencedColumnName =「USER_ID」,insertable = false,updateable = false),因爲Hibernate不允許兩個可變屬性共享相同的列表(userId也使用USER_ID )否則我會在回答公關中得到USER_ID operty必須插入=假,可更新=假

現在來看看的getAnswer映射

@ManyToOne 
JoinColumns({ 
    JoinColumn(name="USER_ID", referencedColumnName="USER_ID", insertable=false, updateable=false), 
    JoinColumn(name="ANSWER_INDEX", referencedColumnName="INFO_INDEX", insertable=false) 
}) 

因爲,休眠抱怨你不能混用不同的插入和更新的映射

我應該怎麼爲了傳遞它嗎?

保重它是一個LEGACY系統。

問候,

回答

1

根據的getAnswer映射問題

@ManyToOne 
JoinColumns({ 
    JoinColumn(name="USER_ID", referencedColumnName="USER_ID", insertable=false, updateable=false), 
    JoinColumn(name="ANSWER_INDEX", referencedColumnName="INFO_INDEX", insertable=false) 
}) 

Hibernate會抱怨,因爲它不能夠混用不同的插入和更新。注意USER_ID JoinColumn中的可插入和可更新,並且只能在ANSWER_INDEX JoinColumn中插入。

因此,爲了通過它,我成立了ANSWER_INDEX JoinCollumn accortding到

JoinColumn(name="ANSWER_INDEX", referencedColumnName="INFO_INDEX", insertable=false, updateable=false) 

這樣,Hibernate不會抱怨。

而且我成立了一家名爲answerIndex

private Integer answerIndex; 

@Column(name="ANSWER_INDEX", insertable=false) 
public void getAnswerIndex() { 
    return this.answerIndex; 
} 

新的屬性然後在用戶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()); 
} 
2

你會大幅免收嵌入式ID和使用替代PK,而不是簡化您的映射。

如果您需要爲某種目的使用InfoId.index(要訂購問題/答案?您可以指定在list映射中),請將其保留爲常規屬性。

UserId將由ManyToOne取代User;另一個關聯端(在User類中)將映射爲@OneToMany(mappedBy="User")

爲什麼答案映射爲ManyToOne?它不應該是OneToMany(例如對許多答案有1個問題)?無論哪種方式,將類映射到自身並不理想 - 基本上實現了一個效率低下的「鄰接列表」模型層次結構;再加上你的情況,你需要確保它不超過2個級別。我會將QuestionAnswer作爲單獨的類別映射;你可以讓他們實現一個通用的接口或擴展相同的基類(可能是抽象的);無論哪種方式,您都可以享受Hibernate提供的隱式多態。

+0

好CHSS,其實是多對一。我使用它而不是OneToOne,因爲一些問題與OneToOne映射有關。 OneToOne可以映射爲ManyToOne(@JoinColumn中的unique = true)。 INFO_INDEX與任何特定用途無關。只是爲了在LEGACY系統中支持複合主鍵的一個關鍵。我明天會嘗試。問候, – 2009-09-11 03:15:58