sql-serverhibernatenhibernate-criteria

Why do I get 'java.lang.IllegalArgumentException: Not an entity' from hibernate using criteria API


I am trying to wire hibernate into an old project (java8, hibernate 5.6.5) but keep getting "Not an entity" in my first tests. This is when using the Criteria API.

The problem occurs at the following line, in WorkflowHibernateRepo#findAll

Root<WaDAO> root = criteria.from(WaDAO.class);

Please help me understand why this error happens and how to get rid of it.

This is my setup:

I made a DAO class WaDAO

package com.aeon.prov.ddd.infrastructure.workflow;

import java.time.LocalDate;
import java.util.UUID;

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

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
@Entity
@Table(name = "PROV_WfAccess")
public class WaDAO {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)  // Use AUTO for UUID generation
    @Column(name = "Guid", columnDefinition = "uniqueidentifier")
    private UUID Guid;
    @Column private int RichiestaNr;
    @Column private UUID ApprovatoreGuid;   
    @Column private int Stato;
    @Column private LocalDate AggiornatoIl;
    @Column private String Note;
    @Column private int Ruolo;

    public WaDAO() {}
}

a repository class:

package com.aeon.prov.ddd.infrastructure.workflow;

import com.aeon.prov.ddd.infrastructure.base.HibernateUtil;

import java.util.List;
import java.util.UUID;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;


public class WorkflowHibernateRepo {

    public WaDAO findById(UUID id) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        try {
            return session.get(WaDAO.class, id);  
        } finally {
            session.close();  
        }
    }

//    public List<WaDAO> findAll() {
//        Session session = HibernateUtil.getSessionFactory().openSession();
//        try {
//            // Use HQL to fetch all WaDAO entities
//            Query<WaDAO> query = session.createQuery("from com.aeon.prov.ddd.infrastructure.workflow.WaDAO", WaDAO.class);
//            return query.list();
//        } finally {
//            session.close();
//        }
//    }
    
    public List<WaDAO> findAll() {
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            // Using Criteria API to fetch all WaDAO entities
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<WaDAO> criteria = builder.createQuery(WaDAO.class);
            Root<WaDAO> root = criteria.from(WaDAO.class);

            // Define the select query (fetching all entities)
            criteria.select(root);

            // Execute the query and return the list of results
            return session.createQuery(criteria).getResultList();
        }
    }

    public void save(WaDAO record) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            session.saveOrUpdate(record);  
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) transaction.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }

    public void delete(WaDAO record) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            session.delete(record);
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) transaction.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
    }
}

The HibernateUtil class is like this:

package com.aeon.prov.ddd.infrastructure.base;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

    private static SessionFactory sessionFactory;
    
    private static <ClassMetadata> SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");
            System.out.println("Hibernate Configuration loaded");
                        
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
            System.out.println("Hibernate serviceRegistry created");

            SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            
            return sessionFactory;
        }
        catch (Throwable ex) {
            System.out.println("Initial SessionFactory creation failed. " + ex);
            ex.printStackTrace();
            throw new ExceptionInInitializerError(ex);
        }
    }
    
    public static SessionFactory getSessionFactory() {
        if(sessionFactory == null) sessionFactory = buildSessionFactory();
        return sessionFactory;
    }
}

And this is my hibernate.cfg.xml file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "https://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <!-- Database connection settings -->
        <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
        <property name="hibernate.connection.url">jdbc:sqlserver://XXXXXXXXX;databaseName=IF_AZES;encrypt=true;trustServerCertificate=true;</property>
        <property name="hibernate.connection.username">xxxxxx</property>
        <property name="hibernate.connection.password">xxxxxx</property>

        <!-- JDBC connection pool settings -->
        <property name="hibernate.c3p0.min_size">5</property>
        <property name="hibernate.c3p0.max_size">20</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>

        <!-- SQL Dialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="hibernate.show_sql">true</property>

        <!-- Format SQL output for readability -->
        <property name="hibernate.format_sql">true</property>

        <!-- Update the database schema automatically -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- Specify annotated classes (entities) -->
        <mapping class="com.aeon.prov.ddd.infrastructure.workflow.WaDAO"/>
        
    </session-factory>

</hibernate-configuration>


Solution

  • This is because Hibernate doesn't know about your WaDAO entity. You need to register it with Configuration.addAnnotatedClass

    configuration.addAnnotatedClass(WaDAO.class);
    

    Since Hibernate 5 the Configuration.configure() method is broken. If you want to add mapping via hibernate.cfg.xml, use MetadataSources:

    StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
    SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();