Hibernateマッピングの例外-不明なエンティティ
1. 問題
この記事では、Hibernateと、SpringおよびHibernate環境の両方について、org.hibernate.MappingException: Unknown entityの問題と解決策について説明します。
参考文献:
HibernateException:Hibernate 3のスレッドにバインドされたHibernateセッションはありません
「スレッドにバインドされたHibernateセッションがありません」例外がスローされるタイミングとその対処方法を確認します。
2. @Entity注釈がないか無効です
マッピング例外の最も一般的な原因は、単にエンティティクラスmissing 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;
}
}
もう1つの可能性は、the wrong type of @Entity annotationが含まれている可能性があることです。
import org.hibernate.annotations.Entity;
@Entity
public class Foo implements Serializable {
...
非推奨のorg.hibernate.annotations.Entityは、使用するエンティティのタイプが間違っています–何we need is the javax.persistence.Entity:
import javax.persistence.Entity;
@Entity
public class Foo implements Serializable {
...
3. MappingException with Spring
configuration of Hibernate in Springには、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:
org.example.ex.mappingexception.persistence.model.Foo
at o.h.i.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1141)
現在、two solutions to this problemがあります–FooエンティティクラスについてLocalSessionFactoryBeanに伝える2つの方法です。
クラスパス内のpackages to search for entity classesを指定できます。
sessionFactory.setPackagesToScan(
new String[] { "org.example.ex.mappingexception.persistence.model" });
または、単にregister the entity classes directlyをSessionFactoryに入れることができます。
sessionFactory.setAnnotatedClasses(new Class[] { Foo.class });
これらの追加の構成行のいずれかを使用すると、テストは正しく実行され、合格します。
4. MappingExceptionとHibernate
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ファイルにはthe 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
このテストを実行すると、同じマッピング例外が発生します。
org.hibernate.MappingException:
Unknown entity: org.example.ex.mappingexception.persistence.model.Foo
at o.h.i.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1141)
上記の例からすでに明らかなように、構成に欠落しているのはadding the metadata of the entity class – Foo – to the configurationです。
configuration.addAnnotatedClass(Foo.class);
これにより、Fooエンティティを永続化できるテストが修正されます。
5. 結論
この記事では、Unknown entity Mapping Exceptionが発生する理由と、最初にエンティティレベルで、次にSpringとHibernateで、最後にHibernateのみで問題が発生した場合の問題の修正方法を説明しました。
すべての例外の例の実装はthe github projectにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。