Вопрос или проблема
Я пытаюсь интегрировать 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. Давайте подробно рассмотрим, как это исправить и что еще может вызвать данную ошибку.
Причины возникновения ошибки
-
Неправильная регистрация сущности:
В вашей конфигурации Hibernate, указанной в файлеhibernate.cfg.xml
, вы правильно указали классWaDAO
с помощью тега<mapping class="com.aeon.prov.ddd.infrastructure.workflow.WaDAO"/>
. Однако, если вы используете объектConfiguration
для созданияSessionFactory
, необходимо убедиться, что класс зарегистрирован либо через XML-мэппинг, либо с помощью вызоваaddAnnotatedClass
. -
Отсутствие соответствующих аннотаций:
Вы также должны убедиться, что ваш классWaDAO
имеет все необходимые аннотации, что, судя по вашему коду, выполнено правильно (например, аннотации@Entity
,@Table
,@Id
и другие). -
Настройки среды:
Если у вас есть несколько установок или конфигураций 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 и логи выполнения для поиска дополнительных подсказок.