[EJB3] SELECT sur JoinTable
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 :
Code:
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 revanche avec mon Entity manager, pas moyen de parvenir au même résultat !!!!
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
Code:
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} |
Cells
Code:
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} |
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:
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)"), |
et voila ce que je fais dans mon manager:
Code:
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); |
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.
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