Je développe un jeu avec une connexion à une base de données et j'utilise JPA pour conserver mes données. Voici mon entité de jeu:
@Entity
@Table(name = "game")
public class Game implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "game_id")
private int id;
@Column(name = "name")
private String name;
@Column(name = "nbTurns")
private int nbTurns;
@Column(name = "playedOn")
@Temporal(TemporalType.TIMESTAMP)
private Date playedOn;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "game_humans", joinColumns = @JoinColumn(name = "game_id"))
@MapKeyColumn(name = "human_id")
@Column(name = "isDead")
private Map<Human, Boolean> humans;
Et voici mon entité humaine:
@Entity
@Table(name = "human")
public class Human implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "name")
private String name;
@OneToOne
private Building building;
Pour obtenir la liste de tous les humains stockés dans la base de données, j'utilise ce DAO, qui fonctionne très bien et obtient également l'entité Building:
public class HumanDAO implements DAO<Human> {
// ...
public List<Human> getAllHumans() {
TypedQuery<Human> query = em.createQuery("SELECT h FROM human h ORDER BY h.name", Human.class);
return query.getResultList();
}
Le problème est que lorsque j'essaie de faire la même chose pour obtenir la liste de tous les jeux avec la requête JPQL SELECT g FROM game g
, j'obtiens cette erreur:
[EL Info]: 2013-11-25 13:40:27.761--ServerSession(1943119327)--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b
[EL Info]: connection: 2013-11-25 13:40:28.151--ServerSession(1943119327)--file:/Users/amine/Documents/workspace/ZombiesServer/target/classes/_ZombiesServer login successful
[WARNING]
Java.lang.reflect.InvocationTargetException
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
at Java.lang.reflect.Method.invoke(Method.Java:606)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.Java:297)
at Java.lang.Thread.run(Thread.Java:724)
Caused by: Java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager:
Exception Description: Problem compiling [SELECT g FROM game g].
[14, 18] The abstract schema type 'game' is unknown.
at org.Eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.Java:1585)
at org.Eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.Java:1605)
at com.amine.zombies.DAO.GameDAO.getAllGames(GameDAO.Java:80)
at com.amine.zombies.application.Application.main(Application.Java:21)
... 6 more
Tu aurais dû
SELECT g FROM Game g//you have game
mais vous avez game
au lieu de Game
.
L'annotation @Table
est utilisée pour la base de données.
Si vous devez modifier le nom dans votre JPQL
, utilisez l'annotation @Entity
: @Entity(name="nameUsedInJPQL") => nameUsedInJPQL is used in your JPQL.
Si vous ne spécifiez rien dans votre @Entity
, le nom de la classe d'entité, sensible à la casse, est utilisé.
Dans mon cas, j'ai oublié de l'enregistrer dans persistence.xml.
Je viens d'avoir la même situation, mais ma requête JPQL était correcte! Cela s'est produit dans Glassfish 4.1 (version 13) (avec EclipseLink).
Après quelques recherches sur Google et quelques commentaires de code, j'ai découvert que la cause première de "le type de schéma abstrait 'MyEntity' est inconnu}" était une utilisation du code lambda Java 8 à l'intérieur de la classe d'entité .
Il semble qu'aucune fonctionnalité de Java 8 ne soit (encore) prise en charge dans la version d'EclipseLink fournie avec GF. Plus d'infos, voir le rapport de bogue à ce sujet.
J'espère que cela t'aides.
le nom de la classe doit être là, pas le nom de la table dans votre requête SELECT g FROM Game g
Le nom à utiliser pour les requêtes JPQL est défini comme le nom simple de la classe d'entité - Game
ou Human
dans votre cas. Il peut être remplacé par l'attribut name
de l'annotation @Entity
. @Table
est une annotation de mappage physique et n'influence pas le nom de l'entité dans la requête.
Cela fonctionne avec human
car la chaîne de requête n'est pas sensible à la casse.
Nous avons eu le problème en raison d'une mise à jour de la bibliothèque org.Eclipse.persistence.eclipselink de 2.4.0 à 2.5.1. Après la mise à jour vers la version 2.6.2, cela fonctionne à nouveau.