web-dev-qa-db-fra.com

Exception JPA: L'objet: ... n'est pas un type d'entité connu

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?

13
mmutilva

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&amp;nf=1&amp;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. 

5
Lars Tackmann

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>
7
Charles

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.PersistenceProviderlorsque 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:

  • si vous définissezexclude-unlisted-classesàtrue, vous devez également lister les entités dans les éléments class de votre persistence.xml
  • si vous définissezexclude-unlisted-classesàfalse, la couche de persistance peut rechercher les entités regards de l'élément class dans votre persistence.xml.
6
Alberto

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
2
Zak

si vous obtenez seulement cette erreur en junit

essayez d'ajouter ceci dans persistence.xml

<jar-file>file:../classes</jar-file>
1
Kalpesh Soni

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 .

1
Moi Lejter

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.

0
bert

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.

0
John John Pichler

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=&apos;refresh&apos;)"/>

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.

0
Zak

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.

0
Karl Richter