Pregunta

Supongamos una asignación como esta

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

}

Y una pregunta y respuesta asignadas por una clase de información

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

}

En getAnswer, uso ManyToOne en lugar de OneToOne debido a algunos problemas relacionados con la asignación de OneToOne. Un OneToOne se puede asignar como ManyToOne (unique = true en @JoinColumn). INFO_INDEX no está relacionado con ningún propósito específico. Solo una clave para admitir una clave principal compuesta en un sistema LEGACY.

Antes de responder, cuida lo siguiente:

  

Si un objeto tiene un identificador asignado o una clave compuesta, el identificador DEBE ESTAR ASIGNADO a la instancia del objeto ANTES de llamar a save ()

Por lo tanto, debo asignar JoinColumn (name = " USER_ID " ;, referencedColumnName = " USER_ID " ;, insertable = false, updateable = false) en getAnswer porque Hibernate no permite compartir dos propiedades mutables la misma columna (userId también usa USER_ID) de lo contrario, obtendré USER_ID en la propiedad de respuesta, se debe asignar con insertable = false, updateable = false

Ahora eche un vistazo a la asignación getAnswer

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

Al hacerlo, Hibernate se queja de que no se pueden mezclar diferentes insertos y actualizables

¿Qué debo hacer para pasarlo?

Cuídate, es un sistema LEGACY.

saludos,

¿Fue útil?

Solución 2

Según la pregunta en el mapeo 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 quejará porque no permite mezclar diferentes insertables y actualizables. Observe que se puede insertar y actualizar en USER_ID JoinColumn y solo se puede insertar en ANSWER_INDEX JoinColumn.

Entonces, para pasarlo, configuré ANSWER_INDEX JoinCollumn que acorta a

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

De esta manera, Hibernate no se quejará.

Y configuro una nueva propiedad llamada answerIndex

private Integer answerIndex;   

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

Luego en el usuario 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());
}

Otros consejos

Debería drásticamente simplificar su asignación al dejar de lado la identificación integrada y, en su lugar, utilizar un PK sustituto.

Si necesita usar InfoId.index para algún propósito (para ordenar preguntas / respuestas, puede especificar que en la asignación de list ), consérvelo como una propiedad regular .

UserId será reemplazado por ManyToOne en User ; el otro extremo de la asociación (en la clase User ) se asignará como @OneToMany(mappedBy="User")

¿Por qué la respuesta se asigna como ManyToOne ? ¿No debería ser OneToMany (por ejemplo, 1 pregunta para muchas respuestas)? De cualquier manera, la asignación de la clase a sí misma no es lo ideal, básicamente estás implementando una " lista de adyacencias " jerarquía de modelos que es ineficiente; Además, en su caso, deberá asegurarse de que no haya más de 2 niveles. Yo mapearía Question y Answer como clases separadas; puede hacer que implementen una interfaz común o extender la misma clase base (posiblemente abstracta); De cualquier forma, podrá disfrutar del polimorfismo implícito proporcionado por Hibernate.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top