Org.hibernate.Exception.SQLGrammarException

Содержание
  1. Введение
  2. Обзор исключений Hibernate
  3. Session-State-Related Errors
  4. 6.1. NonUniqueObjectException
  5. 6.2. StaleStateException
  6. Ошибки управления схемой
  7. 4.1. SchemaManagementException
  8. 4.2. CommandAcceptanceException
  9. Ошибки выполнения SQL
  10. 5.1. JDBCException
  11. 5.2. SQLGrammarException
  12. 5.3. ConstraintViolationException
  13. 5.4. Исключение данных
  14. 5.6. JDBCConnectionException
  15. 5.7. QueryTimeoutException {
    thrown.expectCause(isA(ConstraintViolationException.class));
    thrown.expectMessage("could not execute statement");

    ;
    ;

    ( ; i <= ; i++) {
    {
    session = sessionFactory.openSession();
    transaction = session.beginTransaction();
    ();
    product.setId();
    product.setName( + i);
    session.save(product);
    transaction.commit();
    } (Exception e) {
    rollbackTransactionQuietly(transaction);
    (e);
    } {
    closeSessionQuietly(session);
    }
    }
    }

  16. Ошибки картирования
  17. 3.1. MappingException
  18. Следовательно,  , если мы столкнемся с этим исключением, нам следует сначала проверить наши сопоставления . 3.2. Исключение аннотации
  19. 3.3. QuerySyntaxException
  20. Чтобы устранить эту ошибку, у нас есть два способа:
  21. Что такое OptimisticLockException?
  22. Как Spring Boot обрабатывает исключения Hibernate?
  23. Проблемы со транзакциями
  24. Ошибки ленивой инициализации
  25. 7.1. LazyInitializationException
  26. 7.2. Инициализация соответствующих ленивых отношений на бизнес-уровне
  27. Проблемы параллелизма
  28. Заключение

Введение

В этом уроке мы обсудим некоторые распространенные исключения, с которыми мы можем столкнуться при работе с Hibernate.

Мы рассмотрим их назначение и некоторые распространенные причины. Кроме того, мы рассмотрим их решения.

Выдается исключение SQLGrammarException, поскольку запрос SQL, сгенерированный Hibernate, имеет неправильный синтаксис SQL. Вы построили запрос неправильно, поэтому не следует объединять значения (особенно строковые) с результатом запроса, поскольку такой код уязвим для возможной атаки SQL-инъекцией.

Обзор исключений Hibernate

Многие условия могут привести к возникновению исключений при использовании Hibernate. Это могут быть ошибки сопоставления, проблемы инфраструктуры, ошибки SQL, нарушения целостности данных, проблемы сеансов и ошибки транзакций.

Эти исключения в основном происходят из HibernateException

.

Однако если мы используем Hibernate в качестве поставщика постоянства JPA, эти исключения могут быть заключены в  PersistenceException .

.

Оба этих базовых класса являются продолжением RuntimeException
. Поэтому они все непроверены. Следовательно, нам не нужно перехватывать или объявлять их везде, где они используются.

Кроме того, большинство из них не подлежат восстановлению. В результате повторная попытка операции не помогла.
Это означает, что мы должны прекратить текущий сеанс при встрече с ними.

Давайте теперь рассмотрим каждый из них по отдельности.

Статус HTTP 500 — обработка запроса не удалась; вложенное исключение — javax.persistence. PersistenceException: org.hibernate.Exception. SQLGrammarException: не удалось извлечь ResultSet

 @Entity
@Table(name = "dishes")

public class Dish {

@Id
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
private long id;

@Column(name = "title_ru", nullable = false, length = 50)
private String titleRu;

@Column(name = "title_eng", nullable = false, length = 50)
private String titleEng;

@Column(name = "description_ru", nullable = false, length = 500)
private String descriptionRu;

@Column(name = "description_eng", nullable = false, length = 500)
private String descriptionEng;

@Column(name = "url", nullable = false, length = 150)
private String url;

@Column(name = "img_url", nullable = false, length = 150)
private String imageUrl;

@Column(name = "weight", nullable = false, length = 5)
private int weight;

@Column(name = "category_id", nullable = false, length = 5)
private int categoryId;

@Column(name = "status", nullable = false, length = 2)
private int status;
далее для всех переменных getter and setter

  
 @RestController
public class ReminderController {

    @Autowired
    private BasicService service;

    @RequestMapping(value = "/dishes", method = RequestMethod.GET)
    @ResponseBody
    public List<Dish> getAllDishes() {
        return service.getAllDishes();
    }
}

  

База данных на Postgresql, создала базу, таблицу создала таким образом:

 create table dishes(
id serial,
title_ru text,
title_eng text,
description_ru text,
description_eng text,
url text,
img_url text,
weight integer,
category_id integer,
status integer);

  

Я получил это исключение, когда пытался получить список с помощью NamedQuery:

org.hibernate.exception.SQLGrammarException: could not execute query

Ниже я упомянул код:

Код класса сущности:

 @Table(name = "tbl_users")
@XmlRootElement
@NamedQueries({@NamedQuery(name = "TblUsers.findAll", query = "SELECT t FROM TblUsers t")});

  

Код орудия DAO:

 org.hibernate.Query query = session.getNamedQuery("TblUsers.findAll");
List list = query.list();

  

Пожалуйста, дайте решение для этого исключения.

Kerrek SB's user avatar

92 золотых значка
876 серебряных знаков
1084 бронзовых знака

спросил 1 авг. 2011 в 13:58

Natarajan Ranganathan's user avatar

ответ дан 20 фев 2013 в 18:12

Dnavir's user avatar

Получите SQL-запрос, который генерирует Hibernate (используя hibernate.show_sql
или, предпочтительнее, журналирование SQL Hibernate
) и выполнить его самостоятельно в базе данных. Скорее всего, это поможет вам двигаться в правильном направлении.

ответ дан 1 авг. 2011 в 17:13

Ryan Stewart's user avatar

Райан Стюарт

21 золотой знак
180 серебряных знаков
199 бронзовых знаков

Попробуйте вот это, может сработает.
Это прекрасно сработало для меня.

1) Аннотация уровня класса.

 @NamedQuery(name="UserDetails.byId" , query="from UserDetails where userId = ?")

  

2) Получить запись с помощью NamedQuery

 Query qry2 = sf.getCurrentSession().getNamedQuery("USER_DETAILS.byName")    ;
        qry2.setString(0, "Angad Bansode");
        List<UserDetails> user = qry2.list();
        for (UserDetails userDetails : user) {
            System.out.println("User Details by named native query  name = " + userDetails.getUserName() + ", aadhaar no  = " + userDetails.getAadharNo());
        }

  

ответ дан 10 авг. 2018 в 8:17

Angad Bansode's user avatar

кажется, что этот вопрос немного устарел, но в любом случае, как только я добавил строку ниже для файлов конфигурации спящего режима, у меня это сработало.

 <property name="show_sql">true</property>

  

ответ дан 9 авг. 2018 в 15:11

Для меня отсутствовал доступ к последовательности для первичного ключа с автоинкрементом. После добавления эта ошибка была устранена.

 GRANT USAGE, SELECT ON ALL
    SEQUENCES IN SCHEMA public
    TO "${user-name}";;

  

ответ дан 5 апр. 2021 в 21:56

Nainesh Patel's user avatar

Наинеш Патель

2 золотых значка
5 серебряных знаков
19 бронзовых знаков

Если вы интересуетесь Java-разработкой, вероятно, вы столкнулись с ошибкой org.hibernate.Exception. SQLGrammarException: не удалось извлечь ResultSet. Если вы хотите понять, что это за ошибка, как ее устранить и как ее избежать в будущем, то вам будет полезна эта статья.

Что такое org.hibernate.Exception. SQLGrammarException: не удалось извлечь ResultSet?

Ошибка org.hibernate.Exception. SQLGrammarException: не удалось извлечь ResultSet, когда Hibernate не может выполнить запрос к базе данных. Эта ошибка является примером SQL-исключения и может быть вызвана множеством причин, которые мы рассмотрим далее.

Как устранить ошибку org.hibernate.exception. SQLGrammarException: could not extract ResultSet?

Для исправления этой ошибки вам нужно найти ее причину. Обычно причиной ошибки является несоответствие запроса и базы данных. Например, вы можете использовать неправильный синтаксис SQL-запроса, не указать правильные параметры запроса или передать неверные типы данных.

Чтобы исправить ошибку org.hibernate.exception. SQLGrammarException: could not extract ResultSet, вы можете сделать следующее:

1. Проверьте соединение с базой данных.

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

2. Проверьте ваш SQL-запрос.

Если ваше соединение с базой данных работает исправно, то следующим шагом будет проверка вашего SQL-запроса. Убедитесь, что ваш запрос правильно записан и соответствует схеме базы данных, которую вы используете в своем приложении. Вы также можете проверить, соответствуют ли ваши типы данных типам данных, которые вы используете в вашем запросе.

3. Проверьте настройки Hibernate.

Ваша ошибка может быть вызвана каким-то несоответствием в настройках Hibernate. Проверьте ваш конфигурационный файл и убедитесь, что вы корректно указали все настройки для вашей базы данных и вашего соединения.

Как избежать ошибки org.hibernate.exception. SQLGrammarException: could not extract ResultSet?

Вы можете избежать ошибки org.hibernate.exception. SQLGrammarException: could not extract ResultSet, если будете следовать нескольким советам:

Читайте также:  Отдел работы со страхователями - Государственное учреждение- Мурманское региональное отделение Фонда социального страхования РФ

1. Проверьте свой код, прежде чем его запустить.

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

2. Используйте параметризованные запросы.

Использование SQL-запросов с параметрами помогает избежать ошибок типа org.hibernate.exception. SQLGrammarException. Это связано с тем, что параметризованные запросы генерируются с использованием правильных типов данных. Это также избавляет от необходимости вручную вставлять значения в SQL-запрос, что может привести к ошибкам.

3. Используйте ORM-библиотеки.

ORM-библиотеки, такие как Hibernate, позволяют вам работать с базами данных без необходимости писать SQL запросы вручную. O RM-библиотеки могут помочь вам избежать ошибок типа org.hibernate.exception. SQLGrammarException, так как они генерируют SQL-запросы автоматически и используют правильные типы данных.

4. Уделяйте внимание настройкам вашего соединения с базой данных.

Убедитесь, что ваше соединение с базой данных работает правильно и использует правильные настройки. Некоторые настройки могут привести к тому, что Hibernate не сможет правильно выполнить запрос к базе данных.

Ошибка org.hibernate.exception. SQLGrammarException: could not extract ResultSet может возникнуть по многим причинам. Она может быть вызвана ошибками в вашем SQL-запросе, проблемами в вашей настройке Hibernate или некоторыми другими факторами. Если вы столкнулись с этой ошибкой, то вам следует провести детальную проверку своей программы и несколько следовать приведенным выше советам, чтобы избежать этой ошибки в будущем.

Let’s now look into errors due to Hibernate session usage errors.

6.1. NonUniqueObjectException


Hibernate doesn’t allow two objects with the same identifier in a single session.

If we try to associate two instances of the same Java class with the same identifier in a single session, we get a NonUniqueObjectException
. We can get the name and identifier of the entity by calling the  getEntityName()
and getIdentifier()
methods.

Чтобы воспроизвести эту ошибку, давайте попробуем сохранить два экземпляра Product
с тем же идентификатором с сеансом:

   
 {
    thrown.expect(isA(NonUniqueObjectException.class));
    thrown.expectMessage(
      "A different object with the same identifier value was already associated with the session");

       ;
       ;

     {
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();

            ();
        product.setId();
        product.setName();
        session.save(product);

        product =  ();
        product.setId();
        product.setName();
        session.save(product);

        transaction.commit();
    }  (Exception e) {
        rollbackTransactionQuietly(transaction);
         (e);
    }  {
        closeSessionQuietly(session);
    }
}
  

Мы получим  NonUniqueObjectException, 
как и ожидалось.

Это исключение часто возникает при повторном подключении отсоединенного объекта к сеансу путем вызова обновления
метод.

Если в сеансе загружен другой экземпляр с тем же идентификатором, мы получим эту ошибку. Чтобы исправить это, мы можем использовать слияние
метод

чтобы повторно прикрепить отсоединенный объект.

6.2. StaleStateException


Вызовы Hibernate StaleStateException
s, когда проверка номера версии или отметки времени не удалась. Это указывает на то, что сеанс содержал устаревшие данные.

Иногда это оборачивается  OptimisticLockException .
.

Эта ошибка обычно возникает при использовании длительных транзакций с управлением версиями.

Кроме того, это также может произойти при попытке обновить или удалить объект, если соответствующая строка базы данных не существует:

     
       {
        thrown.expectCause(isA(StaleStateException.class));
        thrown.expectMessage();

           ;
           ;

         {
            session = sessionFactory.openSession();
            transaction = session.beginTransaction();

                ();
            product1.setId();
            product1.setName();
            session.update(product1);
            transaction.commit();
        }  (Exception e) {
            rollbackTransactionQuietly(transaction);
             (e);
        }  {
            closeSessionQuietly(session);
        }
    }
  

Некоторые другие возможные сценарии:

  • мы не указали правильную стратегию несохраненной стоимости для предприятия
  • два пользователя пытались удалить одну и ту же строку почти одновременно
  • мы вручную задаем значение в автоматически сгенерированном поле идентификатора или версии

Ошибки управления схемой

Автоматическое управление схемой базы данных — еще одно преимущество Hibernate. Например, он может генерировать инструкции DDL для создания или проверки объектов базы данных.

Чтобы использовать эту функцию, нам нужно установить hibernate.hbm2ddl.auto 
имущество соответствующим образом.

Если при управлении схемой возникают проблемы, мы получаем исключение. Разберем эти ошибки.

4.1. SchemaManagementException


Любая проблема, связанная с инфраструктурой при выполнении управления схемой, вызывает SchemaManagementException
.

Для демонстрации давайте проинструктируем Hibernate проверить схему базы данных:

    {
    thrown.expect(SchemaManagementException.class);
    thrown.expectMessage("Schema-validation: missing table");

       getConfiguration();
    cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, );
    cfg.addAnnotatedClass(Product.class);
    cfg.buildSessionFactory();
}
  

Поскольку таблица соответствует Продукту
отсутствует в базе данных, мы получаем исключение проверки схемы при построении S essionFactory
.

Кроме того, для этого исключения возможны и другие сценарии:

  • невозможно подключиться к базе данных для выполнения задач управления схемой
  • схемы нет в базе данных

4.2. CommandAcceptanceException


Любая проблема с выполнением DDL, соответствующего конкретной команде управления схемой, может вызвать CommandAcceptanceException
.

В качестве примера давайте укажем неправильный диалект при настройке  SessionFactory
:

    {
    thrown.expect(SchemaManagementException.class);
    thrown.expectCause(isA(CommandAcceptanceException.class));
    thrown.expectMessage("Halting on error : Error executing DDL");

       getConfiguration();
    cfg.setProperty(AvailableSettings.DIALECT,
      );
    cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, );
    cfg.setProperty(AvailableSettings.HBM2DDL_HALT_ON_ERROR,);
    cfg.getProperties()
      .put(AvailableSettings.HBM2DDL_HALT_ON_ERROR, );

    cfg.addAnnotatedClass(Product.class);
    cfg.buildSessionFactory();
}
  

Здесь мы указали неправильный диалект:  MySQLDialect.
Кроме того, мы указываем Hibernate обновить объекты схемы. Следовательно, операторы DDL, выполняемые Hibernate для обновления базы данных H2, завершатся ошибкой, и мы получим исключение.

По умолчанию Hibernate автоматически регистрирует это исключение и продолжает работу.
Когда мы позже будем использовать SessionFactory, 
мы получаем исключение.

Чтобы гарантировать, что при этой ошибке будет выдано исключение, мы установили свойство  HBM2DDL_HALT_ON_ERROR
до правда
.

Аналогично, есть и другие распространенные причины этой ошибки:

  • Несоответствие имен столбцов между сопоставлением и базой данных
  • Два класса сопоставлены с одной и той же таблицей
  • Имя, используемое для класса или таблицы, является зарезервированным словом в базе данных, например ПОЛЬЗОВАТЕЛЬ
    , например
  • Пользователь, используемый для подключения к базе данных, не имеет необходимых привилегий

Ошибки выполнения SQL

Когда мы вставляем, обновляем, удаляем или запрашиваем данные с помощью Hibernate, он выполняет операторы DML для базы данных с использованием JDBC
. Этот API вызывает SQLException
если операция приводит к ошибкам или предупреждениям.

Hibernate преобразует это исключение в JDBCException
или один из его подходящих подклассов:

  • ConstraintViolationException
  • Исключение данных
  • JDBCConnectionException
  • LockAcquisitionException
  • PessimisticLockException
  • QueryTimeoutException
  • SQLGrammarException
  • GenericJDBCException

Давайте обсудим типичные ошибки.

5.1. JDBCException


JDBCException
всегда вызывается конкретным оператором SQL. Мы можем вызвать getSQL
метод для получения оскорбительного оператора SQL.

Кроме того, мы можем получить базовое SQLException
с getSQLException
метод.

5.2. SQLGrammarException


SQLGrammarException
указывает, что SQL-запрос, отправленный в базу данных, недействителен. Это может быть связано с синтаксической ошибкой или недопустимой ссылкой на объект.

Например, отсутствие таблицы может привести к этой ошибке при запросе данных
:

     
       {
        thrown.expectCause(isA(SQLGrammarException.class));
        thrown.expectMessage("could not prepare statement");

           sessionFactory.openSession();
        NativeQuery<Product> query = session.createNativeQuery("select * from NON_EXISTING_TABLE", Product.class);
        query.getResultList();
    }
  

Также мы можем получить эту ошибку при сохранении данных, если таблица отсутствует:

{
throw.expectCause(isA(SQLGrammarException.class));
throw.expectMessage( «не удалось подготовить оператор»
);

ПолучитьКонфигурацию();
cfg.addAnnotatedClass(Product.class);

cfg.buildSessionFactory();
;
;
{
сеанс = sessionFactory.openSession();
транзакция = session.beginTransaction();
();
продукт.setId();
продукт.setName();
session.save(продукт);
транзакция.commit();
} (Исключение е) {
откатTransactionQuietly (транзакция);
(е);
} {
closeSessionQuietly(сессия);
closeSessionFactoryQuietly(sessionFactory);
}

Некоторые другие возможные причины:

  • Используемая стратегия именования не сопоставляет классы с правильными таблицами
  • Столбец, указанный в @JoinColumn
    не существует

5.3. ConstraintViolationException


A ConstraintViolationException
указывает, что запрошенная операция DML привела к нарушению ограничения целостности. Мы можем получить имя этого ограничения, вызвав getConstraintName
метод.

Распространенной причиной этого исключения является попытка сохранить повторяющиеся записи:

    {
    thrown.expectCause(isA(ConstraintViolationException.class));
    thrown.expectMessage("could not execute statement");

       ;
       ;

     (   ; i <= ; i++) {
         {
            session = sessionFactory.openSession();
            transaction = session.beginTransaction();
                ();
            product.setId();
            product.setName( + i);
            session.save(product);
            transaction.commit();
        }  (Exception e) {
            rollbackTransactionQuietly(transaction);
             (e);
        }  {
            closeSessionQuietly(session);
        }
    }
}
  

Кроме того, сохраняя ноль
значение NOT NULL
столбец в базе данных может вызвать эту ошибку.

Чтобы устранить эту ошибку , мы должны выполнить все проверки на бизнес-уровне
. Более того, ограничения базы данных не должны использоваться для проверки приложений.

5.4. Исключение данных



Исключение данных
указывает, что вычисление оператора SQL привело к какой-либо недопустимой операции, несоответствию типов или неправильному количеству элементов.

Например, использование символьных данных в числовом столбце может вызвать следующую ошибку:

{
throw.expectCause(isA(DataException.class));
throw.expectMessage(

«не удалось подготовить оператор»

);

sessionFactory.getCurrentSession();
Запрос NativeQuery = session.createNativeQuery(
«выберите * из ПРОДУКТА, где id=’wrongTypeId’»
, Продукт.класс);
запрос.getResultList();

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

5.5. IdentifierGenerationException

 

{
thrown.expectCause(isA(DataException.class));
thrown.expectMessage("could not prepare statement");

sessionFactory.getCurrentSession();
NativeQuery<Product> query = session.createNativeQuery(
"select * from PRODUCT where id='wrongTypeId'", Product.class);
query.getResultList();
}





Обычно это исключение генерируется, когда Hibernate не может сгенерировать допустимое значение для идентификатора класса сущности.

Наиболее типичной причиной этого исключения является передача объекта сущности с нулевым значением
идентификатор для save()
метод.

Например, давайте рассмотрим ProductEntity
сущность:

 

   {

    
     Integer id;
     String name;
     String description;

    // Getters and Setters

}
  

Теперь давайте проиллюстрируем исключение на тестовом примере:

 
   {

    thrown.expect(isA(IdentifierGenerationException.class));
    thrown.expectMessage("ids for this class must be manually assigned before calling save(): com.baeldung.hibernate.exception.Product");

       ;
       ;

     {
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();

            ();
        product.setName();

        session.save(product);
        transaction.commit();
    }  (Exception e) {
        rollbackTransactionQuietly(transaction);
         (e);
    }  {
        closeSessionQuietly(session);
    }

}
  

Как показано выше, Hibernate завершается с ошибкой IdentifierGenerationException .
потому что мы пытались сохранить экземпляр объекта, который имеет ноль
значение идентификатора .

Итак, чтобы избежать этого исключения, нам нужно убедиться, что наш идентификатор имеет допустимое значение.

5.6. JDBCConnectionException


A JDBCConectionException
указывает на проблемы связи с базой данных.

Например, выход из строя базы данных или сети может привести к выдаче этого исключения.

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

Чтобы решить эту проблему, мы должны сначала убедиться, что хост базы данных присутствует и работает. Затем мы должны убедиться, что для подключения к базе данных используется правильная аутентификация. Наконец, мы должны проверить, правильно ли установлено значение тайм-аута в пуле соединений.

5.7. QueryTimeoutException

{
thrown.expectCause(isA(ConstraintViolationException.class));
thrown.expectMessage("could not execute statement");

;
;

( ; i <= ; i++) {
{
session = sessionFactory.openSession();
transaction = session.beginTransaction();
();
product.setId();
product.setName( + i);
session.save(product);
transaction.commit();
} (Exception e) {
rollbackTransactionQuietly(transaction);
(e);
} {
closeSessionQuietly(session);
}
}
}





Когда время запроса к базе данных истекает, мы получаем это исключение. Мы также можем видеть это из-за других ошибок, таких как переполнение табличного пространства.



                                 

Это одна из немногих исправимых ошибок, что означает, что мы можем повторить оператор в той же транзакции.

Чтобы решить эту проблему, мы можем увеличить время ожидания запроса для длительных запросов
несколькими способами:

  • Установите тайм-аут

    элемент в @NamedQuery
    или @NamedNativeQuery
    аннотация
  • Вызовите   setHint

    метод Запрос
    интерфейс
  • Вызовите setTimeout

    метод  Транзакции
    интерфейс
  • Вызовите setTimeout

    метод запроса
    интерфейс

Ошибки картирования

Объектно-реляционное сопоставление — главное преимущество Hibernate. В частности, это освобождает нас от необходимости вручную писать операторы SQL.

В то же время от нас требуется указать сопоставление между объектами Java и таблицами базы данных. Соответственно, мы указываем их с помощью аннотаций или через документы сопоставления. Эти сопоставления можно закодировать вручную. Альтернативно мы можем использовать инструменты для их создания.

При указании этих отображений мы можем допускать ошибки. Они могут быть в спецификации сопоставления. Или может возникнуть несоответствие между объектом Java и соответствующей таблицей базы данных.

Такие ошибки отображения порождают исключения. Мы часто сталкиваемся с ними во время первоначальной разработки. Кроме того, мы можем столкнуться с ними при переносе изменений в разные среды.

Давайте разберем эти ошибки на примерах.

3.1. MappingException


Проблема с объектно-реляционным сопоставлением вызывает  MappingException
быть брошенным

:

        {
        thrown.expect(isA(MappingException.class));
        thrown.expectMessage("Unable to locate persister: com.baeldung.hibernate.exception.ProductNotMapped");

            ();
        product.setId();
        product.setName();

           sessionFactory.openSession();
        session.save(product);
    }
  

В приведенном выше коде, когда вы пытаетесь сохранить класс, который не определен как сущность, выдается исключение сопоставления .

Однако ProductNotMapped
для класса не указано какое-либо сопоставление. Следовательно, Hibernate не знает структуру этого класса, как расположены столбцы, и выдает исключение.

Подробный анализ возможных причин и решений см. в  Исключение при отображении в спящем режиме — неизвестный объект
.

Аналогично, другие ошибки также могут вызывать это исключение:

  • Смешивание аннотаций к полям и методам
  • Не удалось указать  @JoinTable
    для @ManyToMany
    ассоциация
  • Конструктор по умолчанию отображаемого класса выдает исключение во время обработки сопоставления

Кроме того, MappingException
имеет несколько подклассов, которые могут указывать на конкретные проблемы с отображением:

AnnotationException – 
проблема с аннотацией

DucateMappingException –
дублированное сопоставление для имени класса, таблицы или свойства

InvalidMappingException – 
сопоставление неверно

MappingNotFoundException – 
картографический ресурс не найден

PropertyNotFoundException – 
ожидаемый метод получения или установки не найден в классе

Следовательно,  , если мы столкнемся с этим исключением, нам следует сначала проверить наши сопоставления
.

3.2. Исключение аннотации


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

 
   {
      id;
       {
         id;
    }

    // standard setter
}
  

Поскольку Hibernate ожидает, что каждый объект будет иметь идентификатор

, мы получим HibernateException
когда мы используем сущность:

        {
        thrown.expect(isA(HibernateException.class));
        thrown.expectMessage();

           getConfiguration();
        cfg.addAnnotatedClass(EntityWithNoId.class);
        cfg.buildSessionFactory();
    }
  

Кроме того, некоторые другие вероятные причины:

  • Неизвестный генератор последовательности, используемый в @GeneratedValue
    аннотация
  • @Temporal
    аннотация, используемая с датой Java 8
    / Время
    класс
  • Целевой объект отсутствует или не существует для @ManyToOne
    или @OneToMany
  • Классы сбора сырья
    используется с аннотациями отношений @OneToMany
    или @ManyToMany
  • Конкретные классы, используемые с аннотациями коллекции @OneToMany
    , @ManyToMany
    или @ElementCollection
    как Hibernate ожидает интерфейсы коллекции

Чтобы устранить это исключение, мы должны сначала проверить конкретную аннотацию, упомянутую в сообщении об ошибке.

3.3. QuerySyntaxException


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

QuerySyntaxException
, как следует из названия, сообщает нам, что указанный запрос имеет неверный синтаксис

.

Наиболее типичной причиной этого исключения является использование имени таблицы вместо имени класса в запросах HQL
.

Например, давайте рассмотрим Произведение
сущность:

Теперь давайте проиллюстрируем исключение на тестовом примере:

Как мы видим, Hibernate завершается с ошибкой UnknowEntityException .
потому что мы использовали ПРОДУКТ
вместо Товар
в нашем запросе .
Другими словами, в нашем запросе мы должны использовать имя сущности, а не имя таблицы.

Каковы исключения Hibernate?
Hibernate преобразует это исключение в JDBCException или один из его подходящих подклассов:

ConstraintViolationException.

Исключение данных.

JDBCConnectionException.

LockAcquisitionException.

PessimisticLockException.

QueryTimeoutException.

SQLGrammarException.

GenericJDBCException.

Исключение спящего режима организации SQLGrammarException не может выполнить оператор?

SQLGrammarException: не удалось выполнить оператор. «орг. S QLGrammarException: не удалось выполнить оператор». Это исключение обычно возникает, когда возникает какая-либо проблема с грамматикой или синтаксисом сгенерированного запроса. Фактическая причина проблемы будет в причине трассировки стека исключений.

    {
    thrown.expectCause(isA(DataException.class));
    thrown.expectMessage("could not prepare statement");

       sessionFactory.getCurrentSession();
    NativeQuery<Product> query = session.createNativeQuery(
      "select * from PRODUCT where id='wrongTypeId'", Product.class);
    query.getResultList();
} Что такое ConstraintViolationException в спящем режиме? 
             

ConstraintViolationException. Это, безусловно, наиболее распространенная причина возникновения исключения DataIntegrityViolationException: исключение Hibernate ConstraintViolationException указывает на то, что операция нарушила ограничение целостности базы данных.

Как обрабатываются исключения в спящем режиме?

Как исправить исключение оптимистической блокировки?

Чтобы устранить эту ошибку, у нас есть два способа:


Получите последний объект из базы данных и установите значения старого объекта, если вам нужно, чтобы эти значения были сохранены в новом объекте, и объедините его.

Для старого объекта установите последнюю версию из базы данных.

Как можно избежать ConstraintViolationException?

Убедитесь, что вы выполняете поиск и вставку в транзакцию, чтобы гарантировать, что кто-то не добавит дубликат между поиском и вставкой, иначе вы получите ConstraintViolationException.

Что такое исключение целостности данных организации Springframework?

org.springframework.dao Исключение, возникающее, когда попытка вставки или обновления данных приводит к нарушению ограничения целостности. Обратите внимание, что это не чисто реляционная концепция; уникальные первичные ключи требуются для большинства типов баз данных.

Что такое OptimisticLockException?

общедоступный класс OptimisticLockException расширяет PersistenceException. Вызывается поставщиком постоянства при возникновении конфликта оптимистической блокировки. Это исключение может быть выброшено как часть вызова API, сброса или во время фиксации. Текущая транзакция, если она активна, будет помечена для отката.

Как Spring Boot обрабатывает исключения Hibernate?

Как реализуется оптимистическая блокировка в спящем режиме?

Как остановить оптимистическую блокировку в спящем режиме?

3 ответа. Если возникает исключение OptimisticLockException, у вас есть два варианта: отменить изменения (и, возможно, обновить текущее состояние), обновить только версию вашей сущности (сущностей) и попытаться зафиксировать ее снова.

https://youtube.com/watch?v=YHiqWYt86p8%3Ffeature%3Doembed

Проблемы со транзакциями

Сделки
определять единицы работы и изоляцию между параллельными действиями. Мы можем разграничить их двумя разными способами. Во-первых, мы можем определить их декларативно, используя аннотации. Во-вторых, мы можем управлять ими программно, используя Hibernate Transaction API .
.

Более того, Hibernate делегирует управление транзакциями менеджеру транзакций. Если транзакция не может быть запущена, зафиксирована или отменена по какой-либо причине, Hibernate выдает исключение.

Обычно мы получаем  TransactionException 
или IlegalStateException
в зависимости от менеджера транзакций.

В качестве иллюстрации попробуем зафиксировать транзакцию, помеченную для отката:

     
       {
        thrown.expect(isA(IllegalStateException.class));
        thrown.expectMessage("Transaction already active");

           ;
           ;
         {
            session = sessionFactory.openSession();
            transaction = session.beginTransaction();

                ();
            product1.setId();
            product1.setName();
            session.save(product1);
            transaction = session.beginTransaction();
            transaction.setRollbackOnly();

            transaction.commit();
        }  (Exception e) {
            rollbackTransactionQuietly(transaction);
             (e);
        }  {
            closeSessionQuietly(session);
        }
    }
  

Аналогичным образом, другие ошибки также могут вызывать исключение:

  • Смешение декларативных и программных транзакций
  • Попытка начать транзакцию, когда в сеансе уже активна другая
  • Попытка зафиксировать или откатить транзакцию без начала транзакции
  • Попытка зафиксировать или откатить транзакцию несколько раз

Ошибки ленивой инициализации

Обычно мы настраиваем ассоциации на ленивую загрузку, чтобы повысить производительность приложения. Ассоциации извлекаются только при первом использовании.

Однако Hibernate требует активного сеанса для получения данных. Если сеанс уже закрыт, когда мы пытаемся получить доступ к неинициализированной ассоциации, мы получаем исключение.

Давайте рассмотрим это исключение и различные способы его исправления.

7.1. LazyInitializationException


LazyInitializationException
указывает на попытку загрузить неинициализированные данные вне активного сеанса.

Мы можем получить эту ошибку во многих сценариях.

Во-первых, мы можем получить это исключение при доступе к ленивому отношению на уровне представления. Причина в том, что сущность была частично загружена на бизнес-уровне и сессия закрылась.

Во-вторых, мы можем получить эту ошибку с помощью Spring Data
если мы используем getOne
метод. Этот метод лениво извлекает экземпляр.

Есть много способов решить это исключение.

Прежде всего, мы можем сделать все отношения жадно загруженными. Но это повлияет на производительность приложения, поскольку мы будем загружать данные, которые не будут использоваться.

Во-вторых, мы можем держать сеанс открытым до тех пор, пока представление не будет визуализировано. Это известно как « Открытая сессия в поле зрения

» и это антипаттерн. Нам следует избегать этого, поскольку у этого есть несколько недостатков.

В-третьих, мы можем открыть еще один сеанс и повторно подключить объект, чтобы получить отношения. Мы можем сделать это, используя слияние
метод на сеансе.

Наконец, мы можем инициализировать необходимые ассоциации на бизнес-уровнях. Мы обсудим это в следующем разделе.

7.2. Инициализация соответствующих ленивых отношений на бизнес-уровне


Есть много способов инициализировать ленивые отношения.

Один из вариантов — инициализировать их, вызвав соответствующие методы объекта. В этом случае Hibernate выполнит несколько запросов к базе данных, что приведет к снижению производительности. Мы называем это проблемой «N+1 SELECT».

Во-вторых, мы можем использовать Fetch Join
чтобы получить данные в одном запросе. Однако для этого нам нужно написать собственный код.

Проблемы параллелизма

Hibernate поддерживает две блокировки
стратегии предотвращения несогласованности базы данных из-за параллельных транзакций – оптимистичный
и пессимистический
. Оба они вызывают исключение в случае конфликта блокировок.

Для поддержки высокого уровня параллелизма и высокой масштабируемости мы обычно используем оптимистический контроль параллелизма с проверкой версий. При этом используются номера версий или временные метки для обнаружения конфликтующих обновлений.

OptimisticLockingException
выбрасывается, чтобы указать на конфликт оптимистических блокировок

. Например, мы получаем эту ошибку, если выполняем два обновления или удаления одного и того же объекта без его обновления после первой операции:

    {
    thrown.expect(isA(OptimisticLockException.class));
    thrown.expectMessage(
        "Batch update returned unexpected row count from update");
    thrown.expectCause(isA(StaleStateException.class));

       ;
       ;

     {
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();

            ();
        product.setId();
        product.setName();
        session.save(product1);
        transaction.commit();
        session.close();

        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
        product = session.get(Product.class, );
        session.createNativeQuery("delete from Product where id=12")
          .executeUpdate();
        // We need to refresh to fix the error.
        
        session.delete(product);
        transaction.commit();
    }  (Exception e) {
        rollbackTransactionQuietly(transaction);
         (e);
    }  {
        closeSessionQuietly(session);
    }
}
  
  • Делайте операции обновления как можно короче.
  • Обновляйте представления сущностей в клиенте как можно чаще.
  • Не кэшируйте сущность или какой-либо объект-значение, представляющий ее.
  • Всегда обновляйте представление объекта на клиенте после обновления.

Заключение

В этой статье мы рассмотрели некоторые распространенные исключения, возникающие при использовании Hibernate. Кроме того, мы исследовали их вероятные причины и способы решения.

Как обычно, полный исходный код можно найти  на GitHub .
.

Оцените статью
ФСС Help
Добавить комментарий