es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Relación de muchos a uno con una condición.

Tengo dos tablas, estudiante y profesor, con una relación ManyToOne. La estructura de las tablas es la siguiente:

estudiante(
id long,
student_id string,
….
teacher_id string,
active boolean
)

profesor(
id long,
teacher_id string,
….
active boolean
)

Estoy utilizando Spring Boot y Hibernate. Aquí, al actualizar una entidad, la columna active de la fila existente en la tabla se establecerá en false y se agregará una nueva fila con un nuevo id (long) y active en true. Es por eso que hay dos valores de id en cada tabla. El problema aquí es que he especificado la relación estudiante-profesor como many to one en mi entidad con la clave externa teacher_id.

@Entity
@Table(name = “estudiante”)
public class Estudiante {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "student_id")
private String studentId;

@ManyToOne
@JoinColumn(name = "teacher_id", referencedColumnName = "teacher_id")
private Profesor profesor;

@Column(name = "active")
@JsonIgnore
private Boolean active = true;

}

@Entity
@Table(name = “profesor”)
public class Profesor {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "teacher_id")
private String teacherId;

@OneToMany(mappedBy = "profesor")
private Set<estudiante> estudiantes = new HashSet<>();

@Column(name = "active")
@JsonIgnore
private Boolean active = true;

}

Pero dado que múltiples profesores pueden tener el mismo teacher_id, esto falla. ¿Hay alguna forma de establecer una condición en la relación para obtener el profesor con active como true? En la tabla, solo habrá un profesor con el id dado y active como true.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Sí, puedes especificar una condición en la relación ManyToOne utilizando la anotación @JoinFormula. Esto te permite especificar una expresión SQL que debería ser utilizada en lugar de una unión de claves externas.

    En tu caso, podrías agregar una condición para solo obtener al profesor con active como verdadero de la siguiente manera:

    @Entity
    @Table(name = "student")
    public class Student {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "student_id")
        private String studentId;
    
        @ManyToOne
        @JoinFormula("(" +
                "SELECT t.id " +
                "FROM teacher t " +
                "WHERE t.teacher_id = teacher_id " +
                "AND t.active = true" +
                ")")
        private Teacher teacher;
    
        @Column(name = "active")
        @JsonIgnore
        private Boolean active = true;
    }
    
    @Entity
    @Table(name = "teacher")
    public class Teacher {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "teacher_id")
        private String teacherId;
    
        @OneToMany(mappedBy = "teacher")
        private Set<student> students = new HashSet<>();
    
        @Column(name = "active")
        @JsonIgnore
        private Boolean active = true;
    }
    

    Aquí, estamos utilizando una subconsulta en la anotación @JoinFormula para seleccionar el id del profesor con teacher_id coincidente y active como verdadero. Esto asegura que solo se obtenga un profesor por cada estudiante.

    Nota: Este enfoque asume que siempre habrá como máximo un profesor con un teacher_id y una columna active dados como verdaderos. Si ese no es el caso, es posible que necesites modificar la expresión SQL en consecuencia.

Comments are closed.