Почему я получаю ‘java.lang.IllegalArgumentException: Not an entity’ от hibernate, используя API критериев?

Вопрос или проблема

Я пытаюсь интегрировать Hibernate в старый проект (java8, hibernate 5.6.5), но постоянно получаю “Не является сущностью” в моих первых тестах. Это происходит при использовании Criteria API.

Проблема возникает на следующей строке, в WorkflowHibernateRepo#findAll

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

Пожалуйста, помогите мне понять, почему возникает эта ошибка и как от неё избавиться.

Вот моя настройка:

Я создал класс DAO 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)  // Используйте AUTO для генерации UUID
    @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() {}
}

Класс репозитория:

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 {
//            // Используйте HQL для получения всех сущностей WaDAO
//            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()) {
            // Использование Criteria API для получения всех сущностей WaDAO
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<WaDAO> criteria = builder.createQuery(WaDAO.class);
            Root<WaDAO> root = criteria.from(WaDAO.class);

            // Определение запросов (получение всех сущностей)
            criteria.select(root);

            // Выполнение запроса и возвращение списка результатов
            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();
        }
    }
}

Класс HibernateUtil выглядит следующим образом:

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 {
            // Создание SessionFactory из hibernate.cfg.xml
            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");
            System.out.println("Конфигурация Hibernate загружена");
                        
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
            System.out.println("serviceRegistry Hibernate создан");

            SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            
            return sessionFactory;
        }
        catch (Throwable ex) {
            System.out.println("Ошибка создания начального SessionFactory. " + ex);
            ex.printStackTrace();
            throw new ExceptionInInitializerError(ex);
        }
    }
    
    public static SessionFactory getSessionFactory() {
        if(sessionFactory == null) sessionFactory = buildSessionFactory();
        return sessionFactory;
    }
}

А вот мой файл hibernate.cfg.xml

<?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>
        <!-- Настройки подключения к базе данных -->
        <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 -->
        <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 Диалект -->
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>

        <!-- Эхо всех выполненных SQL в stdout -->
        <property name="hibernate.show_sql">true</property>

        <!-- Форматирование вывода SQL для удобочитаемости -->
        <property name="hibernate.format_sql">true</property>

        <!-- Автоматическое обновление схемы базы данных -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- Укажите аннотированные классы (сущности) -->
        <mapping class="com.aeon.prov.ddd.infrastructure.workflow.WaDAO"/>
        
    </session-factory>

</hibernate-configuration>

Это происходит потому, что Hibernate не знает о вашей WaDAO сущности. Вам нужно зарегистрировать её с помощью Configuration.addAnnotatedClass

configuration.addAnnotatedClass(WaDAO.class);

И кстати, паттерн Объект доступа к данным (DAO) в Hibernate реализуется объектом Session/EntityManager.

Ответ или решение

Ошибка "java.lang.IllegalArgumentException: Not an entity" в Hibernate, возникающая при использовании Criteria API, часто связана с тем, что Hibernate не распознает указанный класс как сущность. В вашем случае проблема заключается в том, что класс WaDAO не зарегистрирован правильно в конфигурации Hibernate. Давайте подробно рассмотрим, как это исправить и что еще может вызвать данную ошибку.

Причины возникновения ошибки

  1. Неправильная регистрация сущности:
    В вашей конфигурации Hibernate, указанной в файле hibernate.cfg.xml, вы правильно указали класс WaDAO с помощью тега <mapping class="com.aeon.prov.ddd.infrastructure.workflow.WaDAO"/>. Однако, если вы используете объект Configuration для создания SessionFactory, необходимо убедиться, что класс зарегистрирован либо через XML-мэппинг, либо с помощью вызова addAnnotatedClass.

  2. Отсутствие соответствующих аннотаций:
    Вы также должны убедиться, что ваш класс WaDAO имеет все необходимые аннотации, что, судя по вашему коду, выполнено правильно (например, аннотации @Entity, @Table, @Id и другие).

  3. Настройки среды:
    Если у вас есть несколько установок или конфигураций Hibernate, важно удостовериться, что загружается именно та конфигурация, в которой зарегистрирован ваш класс.

Решение проблемы

Чтобы исправить проблему, добавьте в метод создания SessionFactory в классе HibernateUtil явную регистрацию сущности WaDAO:

private static SessionFactory buildSessionFactory() {
    try {
        Configuration configuration = new Configuration();
        configuration.configure("hibernate.cfg.xml");

        // Регистрируем класс WaDAO как аннотированную сущность
        configuration.addAnnotatedClass(WaDAO.class);

        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(configuration.getProperties()).build();

        return configuration.buildSessionFactory(serviceRegistry);
    } catch (Throwable ex) {
        throw new ExceptionInInitializerError(ex);
    }
}

Дополнительные рекомендации

  • Проверка конфигурации: Всегда полезно удостовериться, что конфигурационный файл hibernate.cfg.xml корректный и доступен. Проверяйте логи на наличие ошибок при загрузке конфигурации.

  • Идентификация проблемы: Если проблема сохраняется, попробуйте выполнить простую выборку с использованием HQL, как это было в закомментированной части вашего кода, чтобы понять, сохраняется ли ошибка и в других серверах задач.

  • Обработка ошибок: Обратите внимание на обработку исключений. Вы можете дополнительно логировать исключения, чтобы понимать, на каком конкретно этапе происходит сбой.

Эти корректировки должны помочь вам устранить ошибку "Not an entity" и правильно использовать Criteria API для работы с объектами в Hibernate. Если вы столкнётесь с другими проблемами во время реализации, рекомендуем внимательно просматривать документацию Hibernate и логи выполнения для поиска дополнительных подсказок.

Оцените материал
Добавить комментарий

Капча загружается...