2 votes

Hibernate : requête simple de type " one to many " requêtes infinies

J'ai la structure de tables suivante : Utilisateur , Dialogue , Message . L'utilisateur a une liste de dialogues et une liste de messages. Le dialogue possède une liste d'utilisateurs et une liste de messages. Et le message fait référence au dialogue et à l'utilisateur. Donc

Utilisateur - Dialogue : many to many ,

Message - Utilisateur : many to one ,

Message - Dialogue many to one

Entités :

Dialogue

@Entity
@Table(name = "dialogs")
public class Dialog {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_dialog")
    private Long id;

    @Column(name = "dialog_name")
    private String dialogName;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "dialogs_users",
            joinColumns = @JoinColumn(name = "id_dialog"),
            inverseJoinColumns = @JoinColumn(name = "id_user"))
    private List<User> dialogUsers;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "dialog")
    private List<Message> messages = new ArrayList<>();

    //default constructor and getters setters and hashCode equals toString
}

Utilisateur

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_user")
    private Long id;

    @NotNull
    @Column(name = "full_name")
    private String fullName;

    @NotNull
    @Column(name = "email")
    private String email;

    @NotNull
    @Column(name = "active")
    private boolean active;

    @NotNull
    @Column(name = "password")
    private String password;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user")
    private List<Message> messages;

    @ElementCollection(targetClass = Role.class)
    @CollectionTable(name = "user_roles",
            joinColumns = @JoinColumn(name = "user"))
    @Column(name = "role")
    @Enumerated(EnumType.ORDINAL)
    private List<Role> roles = new ArrayList<>();

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "dialogUsers")
    private List<Dialog> dialogs = new ArrayList<>();

    //default constructor and getters setters and hashCode equals toString
}

Message

@Entity
@Table(name = "messages")
public class Message {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_message")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_dialog")
    private Dialog dialog;

    @Column(name = "value")
    private String value;

    @Column(name = "date_time")
    private LocalDateTime dateTime;

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

    //default constructor and getters setters and hashCode equals toString
}

Ma requête entityManager

@Override
public List<Message> findMessagesByDialog(Long dialogId) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Message> criteria = builder.createQuery(Message.class);
    Root<Dialog> dialog = criteria.from(Dialog.class);

    Join<Dialog, Message> messages = dialog.join(Dialog_.messages);

    criteria.select(messages).where(builder.equal(dialog.get(Dialog_.id), dialogId));
    return entityManager.createQuery(criteria).getResultList();
}

La trace de pile que j'obtiens lorsque j'exécute cette requête

Hibernate: 
    select
        messages1_.id_message as id_messa1_2_,
        messages1_.date_time as date_tim2_2_,
        messages1_.id_dialog as id_dialo4_2_,
        messages1_.id_user as id_user5_2_,
        messages1_.value as value3_2_ 
    from
        dialogs dialog0_ 
    inner join
        messages messages1_ 
            on dialog0_.id_dialog=messages1_.id_dialog 
    where
        dialog0_.id_dialog=1
Hibernate: 
    select
        dialog0_.id_dialog as id_dialo1_0_0_,
        dialog0_.dialog_name as dialog_n2_0_0_ 
    from
        dialogs dialog0_ 
    where
        dialog0_.id_dialog=?
Hibernate: 
    select
        user0_.id_user as id_user1_4_0_,
        user0_.active as active2_4_0_,
        user0_.email as email3_4_0_,
        user0_.full_name as full_nam4_4_0_,
        user0_.password as password5_4_0_ 
    from
        users user0_ 
    where
        user0_.id_user=?
Hibernate: 
    select
        user0_.id_user as id_user1_4_0_,
        user0_.active as active2_4_0_,
        user0_.email as email3_4_0_,
        user0_.full_name as full_nam4_4_0_,
        user0_.password as password5_4_0_ 
    from
        users user0_ 
    where
        user0_.id_user=?
Hibernate: 
    select
        dialoguser0_.id_dialog as id_dialo1_1_0_,
        dialoguser0_.id_user as id_user2_1_0_,
        user1_.id_user as id_user1_4_1_,
        user1_.active as active2_4_1_,
        user1_.email as email3_4_1_,
        user1_.full_name as full_nam4_4_1_,
        user1_.password as password5_4_1_ 
    from
        dialogs_users dialoguser0_ 
    inner join
        users user1_ 
            on dialoguser0_.id_user=user1_.id_user 
    where
        dialoguser0_.id_dialog=?

..et ainsi de suite

Je sais que j'ai des références multiples et qu'une entité en référence une autre, mais toutes les recherches sont paresseuses. On peut également penser que le problème se situe au niveau des méthodes hashCode, equals ou toString ils n'ont aucune référence à d'autres instances (seulement leurs propres champs).

Je n'exclus pas d'avoir fait une erreur dans mes déclarations d'entités.

0voto

chsdk Points 64

Vous pouvez utiliser la méthode de Jackson @JsonIgnore annotation con dialogUsers dans votre Dialog elle empêchera Hibernate de récupérer la liste des utilisateurs lors de la sélection d'une entité Dialog :

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "dialogs_users",
        joinColumns = @JoinColumn(name = "id_dialog"),
        inverseJoinColumns = @JoinColumn(name = "id_user"))
@JsonIgnore
private List<User> dialogUsers;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X