Bonjour,
J'ai un entity Map et un Entity Cells.
Mon entity Map possède une collection de Cells.
J'aimerai récupérer l'ensemble des Cells en fonction d'une Map donnée, ET de caractéristiques spécifiques de Cells données.
Exemple :
Récupérer les Cells de la Map numéro 1 dont les Cells ont une position x entre 6 et 14 et une position y entre 6 et 14
La récupération des Cells tout court est simple, mais je ne parviens pas à affiner ma recherche !
en base de données pas de soucis, je fais ceci :
En revanche avec mon Entity manager, pas moyen de parvenir au même résultat !!!!
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 SELECT * FROM Cells cells where cells.xpos BETWEEN 6 AND 14 and cells.ypos BETWEEN 6 AND 14 and cells.id IN ( SELECT cells_id FROM map_cells m LEFT OUTER JOIN cells c ON (m.map_fk = c.id) where map_fk = 2 )
en effet, map_cells est une table générée lors du déploiement de mes EJB3 via l'annotation @JoinTable(name = "map_cells"), mais je ne possède nullement cet Entity. Je ne peux donc pas y accéder !
J'ai essayer d'utiliser les OUTER JOIN mais en vain
voici mes différents entity :
Map
Cells
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 @Entity(name="Map") @Table(name = "Map") @NamedQueries({ @NamedQuery(name = "findAllMap", query = "select object(m) from Map m"), @NamedQuery(name = "getAllCellsForAmap", query = "select cells from Map map where map.id = ?1"), @NamedQuery(name = "getSpecificsCells", query = "select object(c) from Cells c where c.xPos between ?2 and ?3 and c.yPos between ?4 and ?5 and c in (?1)"), }) public class MapObject implements Serializable { private static final long serialVersionUID = 1939766765854655623L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", nullable = false) private int id; @Column(name = "width") private int width; @Column(name = "height") private int height; @Column(name = "name") private String name; @Column(name = "description") private String description; @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinTable(name = "map_cells", joinColumns = { @JoinColumn(name = "map_fk", nullable = true) }) private Set<Cells> cells; {getters/setters}
pour parvenir à mes fins, j'ai donc fait deux requêtes séparées, et je passe à la seconde le résultat de la première. Ça fonctionne mais dans le cadre d'une Map à 8100 cellules je me retrouve avec un java.lang.StackOverFlowError
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 @Entity(name="Cells") @Table(name = "Cells") public class Cells implements Serializable { private static final long serialVersionUID = -7703983300940405607L; //mAxByC @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", nullable = false) private int id; @Column(name = "xPos") private int xPos; @Column(name = "yPos") private int yPos; @Column(name = "isApproachable") private boolean isApproachable; @Column(name = "picturePath") private String picturePath; @Column(name = "description") private String description; @OneToMany(fetch = FetchType.LAZY) @JoinTable(name = "cells_heroes", joinColumns = { @JoinColumn(name = "cells_fk", nullable = true) }) private Set<Hero> heroes; @OneToMany(fetch = FetchType.LAZY) @JoinTable(name = "cells_resources", joinColumns = { @JoinColumn(name = "cells_fk", nullable = true) }) private Set<Objects> objects; @OneToMany(fetch = FetchType.LAZY) @JoinTable(name = "cells_structures", joinColumns = { @JoinColumn(name = "cells_fk", nullable = true) }) private Set<Structure> structures; // relation unidirectionnelle 1:1 @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "ground_fk", nullable = true) private Ground groundsCell; {getters/setters}
et voila ce que je fais dans mon manager:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 @NamedQuery( name = "getAllCellsForAmap", query = "select cells from Map map where map.id = ?1"), @NamedQuery( name = "getSpecificsCells", query = "select object(c) from Cells c where c.xPos between ?2 and ?3 and c.yPos between ?4 and ?5 and c in (?1)"),
J'avais dans un premier temps regroupé ces deux requête, en imbriquant la requête 1 dans la requête 2 mais cela ne fonctionnait pas.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 Query query1 = entityManager.createNamedQuery("getAllCellsForAmap"); query1.setParameter(1, mapId); Query query = entityManager.createNamedQuery("getSpecificsCells"); query.setParameter(1, query1.getResultList()); query.setParameter(2, xMin); query.setParameter(3, xMax); query.setParameter(4, yMin); query.setParameter(5, yMax);
Enfin dernière info (j'anticipe) je ne veux pas que la Cells possède la Map en clé étrangère! (et oui cela aurait facilité la chose) car lors de l'ajout d'une Map possédant rien que 400 Cells, le processus est très long (pourquoi ? je ne sais pas ?) et j'ai constaté (dans mon cas ... erreur de prog ?) que de mettre une JoinTable était beaucoup plus efficace.
Pouvez vous me dire si il y a un meilleur moyen ?
Je ne trouve vraiment pas de solutions et je ne suis pas du tout expert en JPQL
merci beaucoup
Partager