1. 问题概述

本文将探讨 Hibernate 中常见的 org.hibernate.MappingException: Unknown entity 异常问题及其解决方案,涵盖原生 Hibernate 环境和 Spring 整合 Hibernate 的场景。

2. 缺失或错误的 @Entity 注解

导致映射异常的最常见原因是实体类 缺少 @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;
    }
}

另一种可能是使用了 错误的 @Entity 注解类型

import org.hibernate.annotations.Entity;

@Entity
public class Foo implements Serializable {
    ...

❌ 已废弃的 org.hibernate.annotations.Entity 是错误选择
✅ 正确应使用 javax.persistence.Entity

import javax.persistence.Entity;

@Entity
public class Foo implements Serializable {
    ...

3. Spring 环境下的 MappingException

在 Spring 中配置 Hibernate 时,通常通过 LocalSessionFactoryBean 进行注解扫描来启动 SessionFactory

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

这种基础配置会缺少关键设置,导致使用 SessionFactory 的测试失败:

...
@Autowired
private SessionFactory sessionFactory;

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

抛出预期的 MappingException: Unknown entity

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

⚠️ 两种解决方案:

  1. 指定实体类扫描包路径

    sessionFactory.setPackagesToScan(
    new String[] { "com.baeldung.ex.mappingexception.persistence.model" });
    
  2. 直接注册实体类

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

添加任一配置后,测试即可正常运行。

4. 原生 Hibernate 环境的 MappingException

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

hibernate-mysql.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_hibernate5_exceptions
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create

执行测试同样抛出映射异常:

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

解决方案:在配置中显式添加实体类元数据:

configuration.addAnnotatedClass(Foo.class);

添加后实体即可正常持久化。

5. 总结

本文分析了 Unknown entity 映射异常的三大典型场景:

  1. 实体类注解缺失或错误
  2. Spring 整合时的配置遗漏
  3. 原生 Hibernate 的元数据配置缺失

所有示例代码可在 GitHub 项目 中获取,该项目基于 Eclipse 构建,可直接导入运行。


原始标题:Hibernate Mapping Exception