Excepción de mapeo de Hibernate - Entidad desconocida

Top de persistencia

Acabo de anunciar el nuevo curso Learn Spring , centrado en los fundamentos de Spring 5 y Spring Boot 2:

>> VER EL CURSO

1. El problema

Este artículo discutirá org.hibernate.MappingException : problema de entidad desconocida y soluciones, tanto para Hibernate como para entornos Spring e Hibernate.

2. Anotación @Entity faltante o no válida

La causa más común de la excepción de mapeo es simplemente una clase de entidad a la que le falta la anotación @Entity :

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; } }

Otra posibilidad es que tenga el tipo incorrecto de anotación @Entity :

import org.hibernate.annotations.Entity; @Entity public class Foo implements Serializable { ...

El org.hibernate.annotations.Entity obsoleto es el tipo incorrecto de entidad para usar; lo que necesitamos es javax.persistence.Entity :

import javax.persistence.Entity; @Entity public class Foo implements Serializable { ...

3. MappingException con Spring

La configuración de Hibernate en Spring implica arrancar SessionFactory desde el escaneo de anotaciones, a través de LocalSessionFactoryBean :

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

A esta configuración simple de Session Factory Bean le falta un ingrediente clave, y una prueba que intente usar SessionFactory fallará:

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

La excepción es, como se esperaba, la MappingException: entidad desconocida :

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

Ahora, hay dos soluciones para este problema : dos formas de informar al LocalSessionFactoryBean sobre la clase de entidad Foo .

Podemos especificar qué paquetes buscar clases de entidad en la ruta de clases:

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

O simplemente podemos registrar las clases de entidad directamente en Session Factory:

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

Con cualquiera de estas líneas de configuración adicionales, la prueba ahora se ejecutará correctamente y pasará.

4. MappingException con Hibernate

Veamos ahora el error al usar solo 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; } }

El archivo hibernate-mysql.properties contiene las propiedades de configuración de Hibernate :

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

La ejecución de esta prueba dará como resultado la misma excepción de mapeo:

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

Como probablemente ya esté claro en el ejemplo anterior, lo que falta en la configuración es agregar los metadatos de la clase de entidad, Foo , a la configuración :

configuration.addAnnotatedClass(Foo.class);

Esto corrige la prueba, que ahora puede persistir en la entidad Foo.

5. Conclusión

Este artículo ilustró por qué puede ocurrir la excepción de mapeo de entidad desconocida y cómo solucionar el problema cuando ocurre, primero a nivel de entidad, luego con Spring e Hibernate y finalmente, solo con Hibernate solo.

La implementación de todos los ejemplos de excepciones se puede encontrar en el proyecto github; este es un proyecto basado en Eclipse, por lo que debería ser fácil de importar y ejecutar como está.

Fondo de persistencia

Acabo de anunciar el nuevo curso Learn Spring , centrado en los fundamentos de Spring 5 y Spring Boot 2:

>> VER EL CURSO