Question

Supposons un mappage comme celui-ci

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

}

Et une question et une réponse mappées par une classe d'informations

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

}

Dans getAnswer, j'utilise ManyToOne au lieu de OneToOne en raison de problèmes liés au mappage OneToOne. Un OneToOne peut être mappé en tant que ManyToOne (unique = true dans @JoinColumn). INFO_INDEX n'est associé à aucun objectif spécifique. Juste une clé pour supporter une clé primaire composée dans un système LEGACY.

Avant de répondre, prenez soin de ce qui suit:

  

Si un objet a un identifiant attribué ou une clé composite, l'identifiant DEVRAIT ÊTRE ASSIGNÉ à l'instance d'objet AVANT d'appeler save ()

Je dois donc mapper JoinColumn (name = "USER_ID", référencéColumnName = " USER_ID ", insertable = false, updateable = false) dans getAnswer car Hibernate n'autorise pas deux propriétés mutables. la même colonne (userId utilise également USER_ID), sinon j'obtiendra USER_ID dans la propriété de réponse doit être mappé avec insertable = false, updateable = false

Maintenant, jetez un oeil à la cartographie getAnswer

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

Parce qu'Hibernate se plaint de ne pas pouvoir mélanger différents éléments insérables et modifiables

Que dois-je faire pour le réussir?

Attention, c’est un système LEGACY.

salutations

Était-ce utile?

La solution 2

Selon la question de la mappage getAnswer

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

Hibernate se plaindra car il ne permet pas de mélanger différents types d’insertion et de mise à jour. Notez un élément insérable et modifiable dans USER_ID JoinColumn et uniquement insérable dans ANSWER_INDEX JoinColumn.

Donc, pour le transmettre, j'ai configuré ANSWER_INDEX JoinCollumn en fonction de

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

De cette façon, Hibernate ne se plaindra pas.

Et j'ai créé une nouvelle propriété appelée answerIndex

private Integer answerIndex;   

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

Puis dans User 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());
}

Autres conseils

Vous souhaitez radicalement simplifier votre correspondance en renonçant à l'identifiant intégré et en utilisant plutôt une clé de substitution.

Si vous devez utiliser InfoId.index à des fins particulières (pour commander des questions / réponses? vous pouvez spécifier cela dans le mappage list ), conservez-le en tant que propriété standard. .

UserId sera remplacé par ManyToOne sur Utilisateur ; l'autre extrémité de l'association (dans la classe User ) sera mappée en tant que @OneToMany (mappedBy = "quot User")

Pourquoi mapper la réponse en tant que ManyToOne ? Ne devrait-il pas s'agir de OneToMany (par exemple, une question à plusieurs réponses)? Dans les deux cas, le mappage d'une classe sur elle-même est loin d'être idéal: vous implémentez une "liste de contiguïté". hiérarchie des modèles qui est inefficace; De plus, dans votre cas, vous devez vous assurer qu'il ne s'agit pas de plus de 2 niveaux. Je mapperais Question et Réponse en tant que classes séparées; vous pouvez les faire implémenter une interface commune ou étendre la même classe de base (éventuellement abstraite); Dans tous les cas, vous pourrez profiter du polymorphisme implicite fourni par Hibernate.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top