1. 問題
本文將討論 org.hibernate.MappingException:未知實體 問題的解決方案,包括針對 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 並不是合適的實體類型——我們需要的是 jakarta.persistence.Entity:
import jakarta.persistence.Entity;
@Entity
public class Foo implements Serializable {
...3. 在 Spring 中使用 MappingException
使用 Spring 配置 Hibernate 涉及通過註解掃描從 SessionFactory 進行啓動,使用 LocalSessionFactoryBean:
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
...
return sessionFactory;
}這個簡單的 Session Factory Bean 配置缺少關鍵要素,並且嘗試使用 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)現在,解決此問題的有兩種方法 – 兩種方式來告知LocalSessionFactoryBean關於Foo實體類的相關信息。
我們可以指定 classpath 中要搜索實體類的包:
sessionFactory.setPackagesToScan(
new String[] { "com.baeldung.ex.mappingexception.persistence.model" });我們也可以直接將實體類註冊到Session Factory中:
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 配置屬性:
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)正如上例所示,配置中缺失的部分是將實體類的元數據——Foo——添加到配置中:
configuration.addAnnotatedClass(Foo.class);此項修復了測試 – 現在能夠持久保存 Foo 實體。
5. 結論
本文闡述了 Unknown entity Mapping Exception 發生的原理,以及如何解決該問題,首先在實體層面,然後是與 Spring 和 Hibernate 的關聯,最後僅針對 Hibernate 本身進行解決。