Exceção de mapeamento de hibernação - entidade desconhecida

Exceção de mapeamento de hibernação - entidade desconhecida

1. O problema

Este artigo vai discutir o problema e as soluções deorg.hibernate.MappingException: Unknown entity, tanto para o Hibernate quanto para um ambiente Spring e Hibernate.

Leitura adicional:

Inicializando o Hibernate 5 com Spring

Um guia rápido e prático para integrar o Hibernate 5 ao Spring.

Read more

@Immutable no Hibernate

Um guia rápido e prático da anotação @Immutable no Hibernate

Read more

HibernateException: Nenhuma sessão de hibernação vinculada ao thread no Hibernate 3

Descubra quando a exceção "Nenhuma sessão de hibernação vinculada ao encadeamento" é lançada e como lidar com isso.

Read more

2. Anotação@Entity ausente ou inválida

A causa mais comum para a exceção de mapeamento é simplesmente uma classe de entidademissing 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;
    }
}

Outra possibilidade é que possa terthe wrong type of @Entity annotation:

import org.hibernate.annotations.Entity;

@Entity
public class Foo implements Serializable {
    ...

Oorg.hibernate.annotations.Entity obsoleto é o tipo errado de entidade para usar - qualwe need is the javax.persistence.Entity:

import javax.persistence.Entity;

@Entity
public class Foo implements Serializable {
    ...

3. MappingException com Spring

Oconfiguration of Hibernate in Spring envolve a inicialização deSessionFactory da varredura de anotação, por meio de umLocalSessionFactoryBean:

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

Esta configuração simples do Session Factory Bean está faltando um ingrediente chave, e um teste tentando usar oSessionFactory falhará:

...
@Autowired
private SessionFactory sessionFactory;

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

A exceção é, como esperado - oMappingException: Unknown entity:

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

Agora, existemtwo solutions to this problem - duas maneiras de informarLocalSessionFactoryBean sobre a classe de entidadeFoo.

Podemos especificar quaispackages to search for entity classes no caminho de classe:

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

Ou podemos simplesmenteregister the entity classes directly na Session Factory:

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

Com qualquer uma dessas linhas de configuração adicionais, o teste agora será executado corretamente e será aprovado.

4. MappingException com Hibernate

Vamos ver agora o erro ao usar apenas o 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;
    }
}

O arquivohibernate-mysql.properties contémthe 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

A execução deste teste resultará na mesma exceção de mapeamento:

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

Como provavelmente já está claro no exemplo acima, o que está faltando na configuração éadding the metadata of the entity class – Foo – to the configuration:

configuration.addAnnotatedClass(Foo.class);

Isso corrige o teste - que agora é capaz de persistir na entidade Foo.

5. Conclusão

Este artigo ilustrou por que a exceção de mapeamento de entidade desconhecida pode ocorrer e como corrigir o problema quando ocorre, primeiro no nível da entidade, depois com Spring e Hibernate e, finalmente, apenas com o Hibernate.

A implementação de todos os exemplos de exceções pode ser encontrada emthe github project - este é um projeto baseado em Eclipse, portanto, deve ser fácil de importar e executar como está.