Hibernate 未知实体映射异常
Contents
1. 问题
本文将讨论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;
}
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.blogdemo.ex.mappingexception.persistence.model.Foo
at o.h.i.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1141)
现在,这个问题有两种解决方案——两种方法告诉LocalSessionFactoryBean Foo实体类。
我们可以指定在类路径中搜索实体类的包:
sessionFactory.setPackagesToScan(
new String[] { "com.blogdemo.ex.mappingexception.persistence.model" });
或者我们可以简单地将实体类直接注册到会话工厂中:
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_hibernate4_exceptions
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create
运行此测试将导致相同的映射异常:
org.hibernate.MappingException:
Unknown entity: com.blogdemo.ex.mappingexception.persistence.model.Foo
at o.h.i.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1141)
正如从上面的示例中可能已经清楚的那样,配置中缺少的是将实体类的元数据 - Foo - 添加到配置中:
configuration.addAnnotatedClass(Foo.class);
这修复了测试——它现在能够持久化 Foo 实体。