Je suis nouveau dans JPA et j'ai des problèmes avec la génération automatique de valeurs de clé primaire.
J'ai l'entité suivante:
package jpatest.entities;
import Java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
private String someProperty;
public String getSomeProperty() {
return someProperty;
}
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public MyEntity() {
}
public MyEntity(String someProperty) {
this.someProperty = someProperty;
}
@Override
public String toString() {
return "jpatest.entities.MyEntity[id=" + id + "]";
}
}
et la méthode principale suivante dans une autre classe:
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPATestPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
MyEntity e = new MyEntity("some value");
em.persist(e); /* (exception thrown here) */
em.getTransaction().commit();
em.close();
emf.close();
}
Ceci est mon unité de persistance:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://Java.Sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://Java.Sun.com/xml/ns/persistence http://Java.Sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="JPATestPU" transaction-type="RESOURCE_LOCAL">
<provider>Oracle.toplink.essentials.PersistenceProvider</provider>
<class>jpatest.entities.MyEntity</class>
<properties>
<property name="toplink.jdbc.user" value="..."/>
<property name="toplink.jdbc.password" value="..."/>
<property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/jpatest"/>
<property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="toplink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
Lorsque j'exécute le programme, l'exception suivante apparaît dans la ligne marquée du commentaire approprié:
Exception in thread "main" Java.lang.IllegalArgumentException: Object: jpatest.entities.MyEntity[id=null] is not a known entity type.
at Oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.Java:3212)
at Oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerImpl.persist(EntityManagerImpl.Java:205)
at jpatest.Main.main(Main.Java:...)
Qu'est-ce que je rate?
TopLink exigeait que vous définissiez explicitement GenerationType.IDENTITY pour MySQL. Modifiez-le ainsi et supprimez la base de données. Ensuite, essayez de réexécuter votre échantillon. Vous pouvez également vouloir définir explicitement la plate-forme de base de données:
<property name="toplink.platform.class.name"
value="Oracle.toplink.platform.database.MySQL4Platform"/>
De plus, je me souviens vaguement que vous devez exécuter Toplink avec son agent Java afin de le faire fonctionner correctement avec un resourceman entitymanager de ressources local.
J'ai toutefois réussi à utiliser votre exemple avec EclipseLink (que vous devriez utiliser car Toplink est obsolète). Le seul problème étant que je n’avais pas le serveur MySQL à portée de main, je l’ai donc utilisé avec H2. J'ai utilisé le pom.xml Maven suivant pour résoudre les dépendances:
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.randompage</groupId>
<artifactId>sandbox</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<name>sandbox</name>
<repositories>
<repository>
<id>EclipseLink Repo</id>
<url>http://www.Eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.Eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.2.130</version>
</dependency>
</dependencies>
</project>
et ce persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://Java.Sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://Java.Sun.com/xml/ns/persistence http://Java.Sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="JPATestPU" transaction-type="RESOURCE_LOCAL">
<provider>
org.Eclipse.persistence.jpa.PersistenceProvider
</provider>
<class>org.randompage.MyEntity</class>
<properties>
<property name="javax.persistence.jdbc.user" value="johndoe"/>
<property name="javax.persistence.jdbc.password" value="secret"/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:~/.h2/testdb;FILE_LOCK=NO"/>
<property name="eclipselink.ddl-generation" value="create-tables"/>
<property name="eclipselink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
</persistence>
Avec ces paramètres, votre code a fonctionné comme prévu.
J'ai rencontré le même problème avec NetBeans IDE 6.9.
Apparemment, c'est un problème connu. Voir http://wiki.Eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_101:_20100218:_Descriptor.javaClass_is_null_on_a_container_EM_for_a_specific_case . Voir aussi http://netbeans.org/bugzilla/show_bug.cgi?id=181068 .
J'ai ajouté la dernière ligne ci-dessous à persistence.xml et cela a été corrigé.
<provider>org.Eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- Add the following to work around exception issue -->
<exclude-unlisted-classes>false</exclude-unlisted-classes>
Comme Charles a souligné dans sa réponse , le problème n'est pas la génération d'identifiant, mais la couche de persistance ne trouvant pas l'entité.
En tant que vous, je suis également nouveau à JPA. J'ai essayé d'écrire une application JPA "Hello World" en utilisantorg.Eclipse.persistence.jpa.PersistenceProvider
lorsque j'ai eu cette erreur. La solution de contournement mentionnée a également fonctionné pour moi. De plus, j'ai trouvé par essai d'erreur que pour déclarer vos entités, vous devez toujours annoter @entity
dans chaque entité et:
exclude-unlisted-classes
àtrue
, vous devez également lister les entités dans les éléments class
de votre persistence.xml
exclude-unlisted-classes
àfalse
, la couche de persistance peut rechercher les entités regards de l'élément class
dans votre persistence.xml
.J'utilise cette syntaxe plutôt que de taper AUTO
@javax.persistence.Id
@javax.persistence.GeneratedValue(strategy = GenerationType.IDENTITY)
Ensuite, j'utilise le type simple "long" pour les identifiants avec un l minuscule:
private long taskID;
Cela peut ne pas être lié, mais je spécifie également un nom de table différent pour mes entités:
@javax.persistence.Entity(name = "Tasks")
public class Task implements Serializable
si vous obtenez seulement cette erreur en junit
essayez d'ajouter ceci dans persistence.xml
<jar-file>file:../classes</jar-file>
J'ai rencontré la même exception lors du déploiement d'applications Web sur GlassFish v3 (qui utilise EclipseLink en tant que fournisseur JPA). Je ne suis pas sûr que ce soit le même scénario que ci-dessus - mais l'explication de ce bogue dans mon cas pourrait aider les autres :-) - il s'avère qu'il y a un bogue dans EclipseLink, lorsqu'il est exécuté sous OSGi (comme dans GlassFish), ce qui conduit EclipseLink pour conserver une "ancienne" version de la classe d'entité lors du redéploiement, ce qui entraîne cette exception. Le rapport de bug est ici .
Autant que je sache, chaque fois que j'obtiens cette erreur, je ne fais que redémarrer Glassfish. Fonctionne à chaque fois.
Vous pouvez essayer de laisser la définition en dehors du fichier persistence.xml. Le fournisseur de persistance doit ensuite analyser toutes les classes du chemin de classe pour les annotations @Entity.
Vérifiez le dossier de sortie de la classe d'Eclipse. Parfois, vous modifiez le fichier XML et celui-ci n'a pas été mis à jour.
Je dois également ajouter un autre élément à mon persistence.xml lors de la modification des paramètres class/table afin que le gestionnaire d'événements sache créer/mettre à jour des tables:
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(SchemaAction='refresh')"/>
Si je veux un nouveau départ, j'utilise plutôt:
<!--<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(SchemaAction='dropDB,add')"/>
-->
J'ai remarqué que dans votre persistence.xml, la gestion du schéma est uniquement définie sur "créer des tables", par opposition à la suppression/création ou à la mise à jour.
La combinaison du déploiement à partir de NetBeans 8.2 sur Glassfish 4.1 sur un projet Maven avec la fonction "Débogage" d'un projet peut provoquer le ré-déploiement d'une version obsolète (il est difficile de localiser le problème).
Arrêtez GlassFish, supprimez [glassfish base]/glassfish/domains/[domain name]/generated/
, redémarrez et redéployez.