Exception de mise en correspondance Hibernate - Entité inconnue

Exception de mise en correspondance Hibernate - Entité inconnue

1. Le problème

Cet article va discuter du problème et des solutions deorg.hibernate.MappingException: Unknown entity, à la fois pour Hibernate ainsi que pour un environnement Spring et Hibernate.

Lectures complémentaires:

Démarrer Hibernate 5 avec Spring

Un guide rapide et pratique pour intégrer Hibernate 5 à Spring.

Read more

@Immutable à Hibernate

Un guide rapide et pratique sur l'annotation @Immutable dans Hibernate

Read more

HibernateException: aucune session Hibernate liée à un thread dans Hibernate 3

Découvrez quand une exception "No Hibernate Session Bound to Thread" est générée et comment la gérer.

Read more

2. Annotation@Entity manquante ou non valide

La cause la plus courante de l'exception de mappage est simplement une classe d'entitémissing the @Entity annotation:

public class Foo implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    public Foo() {
        super();
    }

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
}

Une autre possibilité est qu'il peut avoirthe wrong type of @Entity annotation:

import org.hibernate.annotations.Entity;

@Entity
public class Foo implements Serializable {
    ...

Leorg.hibernate.annotations.Entity obsolète est le mauvais type d'entité à utiliser - quewe need is the javax.persistence.Entity:

import javax.persistence.Entity;

@Entity
public class Foo implements Serializable {
    ...

3. MappingException avec Spring

Leconfiguration of Hibernate in Spring implique l'amorçage desSessionFactory à partir de l'analyse des annotations, via unLocalSessionFactoryBean:

@Bean
public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(restDataSource());
    ...
    return sessionFactory;
}

Il manque un ingrédient clé à cette configuration simple du Session Factory Bean, et un test essayant d'utiliser lesSessionFactory échouera:

...
@Autowired
private SessionFactory sessionFactory;

@Test(expected = MappingException.class)
@Transactional
public void givenEntityIsPersisted_thenException() {
    sessionFactory.getCurrentSession().saveOrUpdate(new Foo());
}

L'exception est, comme prévu - lesMappingException: Unknown entity:

org.hibernate.MappingException: Unknown entity:
org.example.ex.mappingexception.persistence.model.Foo
    at o.h.i.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1141)

Maintenant, il y atwo solutions to this problem - deux manières de dire auxLocalSessionFactoryBean la classe d'entitéFoo.

Nous pouvons spécifier quelspackages to search for entity classes dans le chemin de classe:

sessionFactory.setPackagesToScan(
  new String[] { "org.example.ex.mappingexception.persistence.model" });

Ou nous pouvons simplementregister the entity classes directly dans la fabrique de session:

sessionFactory.setAnnotatedClasses(new Class[] { Foo.class });

Avec l'une ou l'autre de ces lignes de configuration supplémentaires, le test s'exécutera correctement et passera.

4. MappingException avec Hibernate

Voyons maintenant l'erreur lorsque vous utilisez uniquement Hibernate:

public class Cause4MappingExceptionIntegrationTest {

    @Test
    public void givenEntityIsPersisted_thenException() throws IOException {
        SessionFactory sessionFactory = configureSessionFactory();

        Session session = sessionFactory.openSession();
        session.beginTransaction();
        session.saveOrUpdate(new Foo());
        session.getTransaction().commit();
    }

    private SessionFactory configureSessionFactory() throws IOException {
        Configuration configuration = new Configuration();
        InputStream inputStream = this.getClass().getClassLoader().
          getResourceAsStream("hibernate-mysql.properties");
        Properties hibernateProperties = new Properties();
        hibernateProperties.load(inputStream);
        configuration.setProperties(hibernateProperties);

        // configuration.addAnnotatedClass(Foo.class);

        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().
          applySettings(configuration.getProperties()).buildServiceRegistry();
        SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        return sessionFactory;
    }
}

Le fichierhibernate-mysql.properties contientthe Hibernate configuration properties:

hibernate.connection.username=tutorialuser
hibernate.connection.password=tutorialmy5ql
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.connection.url=jdbc:mysql://localhost:3306/spring_hibernate4_exceptions
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create

L'exécution de ce test entraînera la même exception de mappage:

org.hibernate.MappingException:
  Unknown entity: org.example.ex.mappingexception.persistence.model.Foo
    at o.h.i.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1141)

Comme il ressort probablement déjà de l'exemple ci-dessus, ce qui manque dans la configuration estadding the metadata of the entity class – Foo – to the configuration:

configuration.addAnnotatedClass(Foo.class);

Cela corrige le test - qui est maintenant capable de persister l'entité Foo.

5. Conclusion

Cet article explique pourquoi une exception de mappage d'entité inconnue peut se produire et comment résoudre le problème, tout d'abord au niveau de l'entité, puis avec Spring et Hibernate et enfin, avec Hibernate seul.

L'implémentation de tous les exemples d'exceptions peut être trouvée dansthe github project - il s'agit d'un projet basé sur Eclipse, il devrait donc être facile à importer et à exécuter tel quel.