2

The following code works just fine with Hibernate 4.3, but when I try the same code using Hibernate 5.0 it results in the following error:

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)

Could somebody help me understand why is it happening?


Following is the code being used to test the example:

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 Database Schema (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`)
);
Bacteria
  • 8,406
  • 10
  • 50
  • 67
skip
  • 12,193
  • 32
  • 113
  • 153
  • what is your directory structure – Juned Ahsan Oct 08 '15 at 02:01
  • @JunedAhsan: Its a Java Project in Eclipse IDE with `src` being the source folder in the classpath. `hibernate.cfg.xml` is right under the `src` folder. `Main.java` is in the `client` package, `HibernateUtil.java` in `util` package and `Message.java` in the `entity` package. – skip Oct 08 '15 at 02:06
  • I think its because you didnt set up a default schema property in your hibernate-cfg.xml. Let me take a look, and I'll be right back with the answer – javaguest Oct 14 '15 at 20:01

2 Answers2

11

UPDATED: In Hibernate 5.0.x, configuration with standard service registry is deprecated

Instead you should bootstrap it with Metadata:

In your HibernateUtil class, you should add

   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();

    }

And as a side note, change the ID declaration of your Message Class to

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

So hibernate can properly use mySql's auto increment, otherwise it will throw an exception.

javaguest
  • 399
  • 2
  • 8
  • It doesn't make any difference. I am stilling getting the same error. – skip Oct 15 '15 at 07:24
  • ok, im setting up a new project in order to debug it, are you using maven? – javaguest Oct 15 '15 at 11:37
  • not to sound like an ass, but I recreated your project in eclipse and it worked perfectly. I shared it on github: https://github.com/bruno-cw/pizzadepot/tree/master/Hibernate if you could share yours, it would be a great help to identify whats wrong. I ruled out any problem with db, – javaguest Oct 15 '15 at 12:10
  • No, am not using Maven. Just a Java project in eclipse with jar files in the c.asspath – skip Oct 17 '15 at 02:19
  • Thanks for the project @javaguest, let me try it. – skip Oct 17 '15 at 02:24
  • Hello @javaguest, you seem to be using `4.3.0.Final` version of Hibernate which is working fine at my end too. The same code isn't working with Hibernate 5.0.x version. Could you test your code with Hibernate 5.0.x version and see if it's working? – skip Oct 17 '15 at 02:49
  • I switched to 5.0.0 Final, and I could reproduce the issue. I edited my answer based on that. – javaguest Oct 19 '15 at 11:26
  • Nothing needs to go into `configuration.buildSessionFactory()` call in the `HibernateUtil` class for the `Message` entity to be found. That way, you don't need to use `addAnnotatedClass` (E.g. `configuration.addAnnotatedClass(Message.class)`) as you would be able to do that in your `hibernate.cfg.xml` file using ``. – skip Oct 20 '15 at 09:05
  • yes, i know, but configuration in 5.0 got a major overhaul. Apparently, to use a configuration xml file, you have to use JPA declarations. I'm still looking on how to do it non-programatically. – javaguest Oct 20 '15 at 11:16
  • fixed it: more info here: http://stackoverflow.com/questions/33005348/hibernate-5-org-hibernate-mappingexception-unknown-entity/33134619?noredirect=1#comment54268230_33134619 – javaguest Oct 20 '15 at 12:57
  • Yep, build the `StandardServiceRegistry` first, then build the `Metadata` and then the `SessionFactory` using them. – skip Oct 23 '15 at 06:17
  • It works for me using Hibernate 5.x Why Hibernate always change his configuration setting in every version? :( – fanjavaid Feb 05 '16 at 07:13
0

Alternatively, you could do the following in Hibernate 5+ and have your SessionFactory/Session creating class extend the HibernateHelper class below:

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

specialk1st
  • 1,717
  • 21
  • 20