Bonjour tout le monde

J'ai un problème avec une requête EJB QL : j'aimerai pouvoir charger une liste d'objets directement via la requête, pour des raisons de performance, sans passer par le FetchType.EAGER.

Voici mes 2 classes (Entity Beans) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 
@Entity
public class ParentEntity implements Serializable {
 
    private int id;
    private List<ChildEntity> children;
 
    /** Creates a new instance of ParentEntity */
    public ParentEntity () {
    }
 
    /**
     * Gets the id of this ParentEntity .
     * @return the id
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getId() {
        return this.id;
    }
 
    /**
     * Sets the id of this ParentEntity to the specified value.
     * @param id the new id
     */
    public void setId(int id) {
        this.id = id;
    }
 
    @OneToMany(cascade = {CascadeType.ALL})
    @IndexColumn(name = "index")
    public List<ChildEntity> getChildren() {
        return children;
    }
 
    public void setChildren(List<ChildEntity> children) {
        this.children= children;
    }
 
   @Override
    public int hashCode() {
        return getId();
    }
 
    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof ParentEntity) {
            return getId() == ((ParentEntity) obj).getId();
        }
 
        return false;
    }
}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 
@Entity
public class ChildEntity implements Serializable {
 
    private int id;
    private List<FriendEntity> friends;
 
    /** Creates a new instance of ChildEntity */
    public ChildEntity () {
    }
 
    /**
     * Gets the id of this ChildEntity .
     * @return the id
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getId() {
        return this.id;
    }
 
    /**
     * Sets the id of this ChildEntity to the specified value.
     * @param id the new id
     */
    public void setId(int id) {
        this.id = id;
    }
 
    @OneToMany(cascade = {CascadeType.ALL})
    @IndexColumn(name = "index")
    public List<FriendEntity> getFriends() {
        return friends;
    }
 
    public void setFriends(List<FriendEntity> friends) {
        this.friends= friends;
    }
 
   @Override
    public int hashCode() {
        return getId();
    }
 
    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof ChildEntity) {
            return getId() == ((ChildEntity) obj).getId();
        }
 
        return false;
    }
}
L'exemple est simple : j'ai des parents (ParentEntity). Chaque parent a une liste ordonnée d'enfants (ChildEntity). Chaque enfant a à son tour une liste ordonnée d'amis (FriendEntity).

Je souhaite pouvoir récupérer la liste des enfants connaissant l'id du parent, tout en chargeant la liste d'amis de ceux-ci. J'ai donc écrit cette requête :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
SELECT child 
FROM ParentEntity parent, IN (parent.children) child LEFT JOIN FETCH child.friends 
WHERE parent.id = ?0
Le problème est que je récupère des enfants en double, je ne les récupère pas qu'une seule fois... En fait, je récupère tous les enfants du bon parent * leur nombre d'amis (s'il y a 4 enfants, et que chacun ont 3 amis, ma liste contient 3 fois la liste des enfants soit 12 éléments retournés).

Je n'arrive donc pas à retourner cette liste proprement, le tout en conservant l'ordre (la liste des enfants est ordonnée).
J'ai essayé ceci :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
SELECT DISTINCT child 
FROM ParentEntity parent, IN (parent.children) child LEFT JOIN FETCH child.friends 
WHERE parent.id = ?0
Cela me renvoie bien la bonne liste contenant une seule fois chaque enfant, mais dans le désordre !

C'est assez étrange, car la requête suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
SELECT child 
FROM ParentEntity parent, IN (parent.children) child 
WHERE parent.id = ?0
me renvoie bien la liste correcte (bon nombre d'éléments, et ordonnée) mais ne charge pas la liste d'amis des enfants...

Je suis perdu... je ne sais pas comment faire...

Merci d'avance pour les pistes que vous pourrez me donner