JEE Back-end

Retours sur les exercices sur les mappings Hibernate

Video version naive

@Entity
public class User implements WithId<String> {
    @Id
    private String username;

    ...
}
@Entity
public class Video implements WithId<Long> {
    @Id
    @GeneratedValue
    private Long id;

    private String name;
    ...

}

Video version naive

@Entity
public class Vote {

    public static enum VoteType {UPVOTE(1),DOWNVOTE(-1)};

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn
    private Video video;

    private VoteType voteType;

    ...

}

Ce mapping ne garantie pas en BD qu'une personne ne peut pas voter plusieurs fois pour une même video :(

Video better

Une meilleure modélisation consiste à faire une clée composite Video + User.

public class VoteId implements Serializable {

    private User user;
    private Video video;

    ...
}    
@Entity
@IdClass(VoteId.class)
public class Vote {

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    private User user;


    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    private Video video;

    private VoteType voteType;    

    ...
}

Mapping bi-directionnel

    @OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    @JoinColumn(name = "phoneNumber_id")
    private PhoneNumber phoneNumber;

    @ManyToOne(fetch = FetchType.LAZY)
    private University university;

    @ManyToMany
    private Set<Lecture>  lectures;

    @OneToMany(cascade = CascadeType.ALL,mappedBy = "student")
    @OrderBy("date")
    private List<Remark> remarks;

La classe Student est responsable de toutes les relations. C'est un choix arbitraire pour Lecture.

De l'autre coté

public class Lecture {

    @Id
    @GeneratedValue
    private Long id;
    private String title;
    @ManyToMany(mappedBy="lectures")
    private Set<Student> students;
    ...

Suppresion d'un cours pour un étudiant

public void removeLecture(Student student, Lecture lecture){
        Objects.requireNonNull(student.getId());
        Objects.requireNonNull(lecture.getId());
        inTransaction(em -> {
            var q="SELECT s FROM Student s LEFT JOIN FETCH s.lectures WHERE s.id = :id";
            var query=em.createQuery(q,Student.class);
            query.setParameter("id",student.getId());
            var studentPersistent = query.getSingleResult();
            ...
            var lecturePersistent = em.find(Lecture.class,lecture.getId());
            ...
            studentPersistent.remove(lecturePersistent);
            return null;
        });
    }    
public class Student{
        ...

    public void remove(Lecture lecture) {
        lectures.remove(lecture);
        lecture.getStudents().remove(this);
    }

}