Hibernate 5: org.hibernate.MappingException: неизвестный объект

Следующий код отлично работает с Hibernate 4.3, но когда я пробую тот же код с помощью Hibernate 5.0, это приводит к следующей ошибке:

Exception in thread "main" org.hibernate.MappingException: Unknown entity: entity.Message
    at org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:776)
    at org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1451)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:100)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:678)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:670)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:665)
    at client.Main.main(Main.java:14)

Может ли кто-нибудь помочь мне понять, почему это происходит?


Ниже приведен код, используемый для тестирования примера:

Main.java

package client;
import org.hibernate.Session;
import util.HibernateUtil;
import entity.Message;

public class Main {
    public static void main(String[] args) {        
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();

        Message message = new Message( "Hello Hibernate 5" );

        session.save(message);    

        session.getTransaction().commit();
        session.close();    
    }
}

HibernateUtil.java

package util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {    
    private static final SessionFactory sessionFactory = buildSessionFactory();    
    private static SessionFactory buildSessionFactory() {
        try {           
            Configuration configuration = new Configuration().configure("hibernate.cfg.xml");     
            return configuration.buildSessionFactory( new StandardServiceRegistryBuilder().applySettings( configuration.getProperties() ).build() );
        }
        catch (Throwable ex) {                
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }   
}

Message.java

package entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="message")
public class Message {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="ID")  
    private Long id;

    @Column(name="TEXT")    
    private String text;

    public Message() {}
    public Message(String text) {
        this.text = text;
    }   
}

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>

        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/hello</property>
        <property name="connection.username">root</property>
        <property name="connection.password">pass</property>

        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <mapping class="entity.Message"/>

    </session-factory>
</hibernate-configuration>

Схема базы данных SQL (RDBMS: MYSQL)

CREATE DATABASE `hello`;
USE `hello`;
CREATE TABLE `message` (
`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
`TEXT` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`ID`)
);

person skip    schedule 08.10.2015    source источник
comment
какая у вас структура каталогов   -  person Juned Ahsan    schedule 08.10.2015
comment
@JunedAhsan: это Java-проект в Eclipse IDE, где src является исходной папкой в ​​пути к классам. hibernate.cfg.xml находится прямо под папкой src. Main.java находится в пакете client, HibernateUtil.java в пакете util и Message.java в пакете entity.   -  person skip    schedule 08.10.2015
comment
Я думаю, это потому, что вы не настроили свойство схемы по умолчанию в своем hibernate-cfg.xml. Позвольте мне взглянуть, и я скоро вернусь с ответом   -  person javaguest    schedule 14.10.2015


Ответы (2)


ОБНОВЛЕНО: в Hibernate 5.0.x конфигурация со стандартным реестром служб устарела.

Вместо этого вы должны загрузить его с помощью метаданных:

В вашем классе HibernateUtil вы должны добавить

   private static SessionFactory buildSessionFactory() {
    try {           
        StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
        .configure( "hibernate.cfg.xml" )
        .build();

        Metadata metadata = new MetadataSources( standardRegistry )
        .getMetadataBuilder()
        .build();

        return metadata.getSessionFactoryBuilder().build();

    }

И в качестве примечания измените объявление идентификатора вашего класса сообщений на

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID")  
private Long id;

Таким образом, hibernate может правильно использовать автоинкремент mySql, иначе он выдаст исключение.

person javaguest    schedule 14.10.2015
comment
Это не имеет никакого значения. Я все еще получаю ту же ошибку. - person skip; 15.10.2015
comment
хорошо, я создаю новый проект, чтобы отладить его, вы используете maven? - person javaguest; 15.10.2015
comment
чтобы не звучать как задница, но я воссоздал ваш проект в eclipse, и он отлично сработал. Я поделился им на github: github.com/bruno-cw/pizzadepot/tree/ master/Hibernate, если бы вы могли поделиться своим, было бы здорово определить, что не так. Я исключил любую проблему с БД, - person javaguest; 15.10.2015
comment
Нет, я не использую Maven. Просто проект Java в eclipse с файлами jar в c.asspath - person skip; 17.10.2015
comment
Спасибо за проект @javaguest, позвольте мне попробовать. - person skip; 17.10.2015
comment
Здравствуйте, @javaguest, похоже, вы используете 4.3.0.Final версию Hibernate, которая у меня тоже работает нормально. Тот же код не работает с версией Hibernate 5.0.x. Не могли бы вы протестировать свой код с версией Hibernate 5.0.x и посмотреть, работает ли он? - person skip; 17.10.2015
comment
Я перешел на 5.0.0 Final и смог воспроизвести проблему. Я отредактировал свой ответ на основе этого. - person javaguest; 19.10.2015
comment
Ничего не нужно делать в вызове configuration.buildSessionFactory() в классе HibernateUtil, чтобы сущность Message была найдена. Таким образом, вам не нужно использовать addAnnotatedClass (например, configuration.addAnnotatedClass(Message.class)), поскольку вы можете сделать это в своем файле hibernate.cfg.xml, используя <mapping class="entity.Message"/>. - person skip; 20.10.2015
comment
да, я знаю, но конфигурация в 5.0 подверглась капитальному ремонту. По-видимому, чтобы использовать файл конфигурации xml, вы должны использовать объявления JPA. Я все еще ищу, как это сделать непрограммно. - person javaguest; 20.10.2015
comment
исправлено: больше информации здесь: stackoverflow.com/questions/33005348/ - person javaguest; 20.10.2015
comment
Да, сначала постройте StandardServiceRegistry, затем постройте Metadata, а затем SessionFactory, используя их. - person skip; 23.10.2015
comment
У меня работает с Hibernate 5.x Почему Hibernate всегда меняет настройки конфигурации в каждой версии? :( - person fanjavaid; 05.02.2016

В качестве альтернативы вы можете сделать следующее в Hibernate 5+ и сделать свой SessionFactory/Session создающий класс extend классом HibernateHelper ниже:

package com.company.hibernatehelper;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateHelper {
    private static SessionFactory sessionFactory = null;

    public static SessionFactory getSessionFactory() {
        if(sessionFactory == null) {
        sessionFactory = new  Configuration().configure().buildSessionFactory();
        }
        return sessionFactory;
    }
}

person specialk1st    schedule 01.10.2016