Глава 18. Нативный SL


Удаление постоянных объектов

Session.delete() удалит состояние объекта из базы данных. Однако ваше приложение может
содержать ссылку на удалённый объект. Лучше думать о delete() как о методе, делающем
постоянный экземпляр переходным.

Вы можете удалять объекты в любом порядке, без риска нарушения внешнего ключа. По-прежнему можно
нарушить ограничение NOT NULL в столбце внешнего ключа, удалив объекты в неправильном
порядке. Например, если вы удалите родителя, но забудьте удалить детей.

Java

4. Execute the Query

Изменение постоянных объектов

Транзакционные постоянные экземпляры (т.е. объекты, загруженные, сохранённые, созданные
или запрошенные Session) могут быть обработаны приложением, и любые изменения в постоянном
состоянии будут сохраняться при очистке (flush) Session. Это обсуждается далее
в этой главе. Нет необходимости вызывать конкретный метод (например, update(), который имеет
другое назначение), чтобы ваши модификации сохранялись. Самый простой способ обновить состояние
объекта — загрузить его вызовом load(), а затем манипулировать им напрямую,
когда Session открыт:

DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );
cat.setName(«PK»);
sess.flush(); // изменения в Cat автоматически обнаруживаются и сохраняются

Иногда эта модель программирования неэффективна, так как в одной сессии требуется как SQL
SELECT для загрузки объекта, так и SQL UPDATE для сохранения его обновлённого
состояния. Hibernate предлагает альтернативный подход, используя отсоединённые (detached) экземпляры.

Автоматическое обнаружение состояния

Пользователи Hibernate запросили метод общего назначения, который либо сохраняет переходный экземпляр,
генерируя новый идентификатор, либо обновляет/повторно присоединяет отсоединённый экземпляр, связанный
с его текущим идентификатором. Метод saveOrUpdate() реализует этот функционал.

// в первой сессии
Cat cat = (Cat) firstSession.load(Cat.class, catID);
// в более высоком уровне приложения
Cat mate = new Cat();
cat.setMate(mate);
// позже, в новой сессии
secondSession.saveOrUpdate(cat); // обновить существующее состояние (Cat имеет ненулевой идентификатор)
secondSession.saveOrUpdate(mate); // сохранить новый экземпляр (Mate имеет нулевой идентификатор)

Использование и семантика saveOrUpdate() кажется запутанной для новых пользователей.
Во-первых, если вы не пытаетесь использовать экземпляры из одной сессии в другой новой сессии,
вам не нужно использовать update(), saveOrUpdate() или merge().
Бывает так, что во всём приложении нет вызова ни одого из этих методов.

Обычно update() или saveOrUpdate() используются в следующем сценарии:

saveOrUpdate() выполняет следующие действия:

а merge() очень отличается:

Переходное постоянство (Transitive persistence)

Довольно обременительно сохранять, удалять или повторно присоединять отсоединённые объекты, особенно если
вы имеете дело с графом связанных объектов. Частным случаем является отношение родитель/ребёнок.
Рассмотрим следующий пример:

Читайте также:  Пу саратов самара

Если детям в отношении родитель/ребёнок будут введены значения (например, набор адресов или строк),
их жизненный цикл будет зависеть от родителя, и для удобного «каскадирования»
изменений состояния не потребуется никаких дополнительных действий. Когда родитель будет сохранён,
дочерние объекты с типом значений (value-typed) сохраняются, а когда родитель будет удалён,
дети будут удалены и т.д. Это работает для таких операций, как удаление дочернего объекта из коллекции.
Поскольку объекты с типом значений (value-typed) не могут иметь общие ссылки, Hibernate обнаружит
это и удалит дочерний объект из базы данных.

Теперь рассмотрим один и тот же сценарий с родительскими и дочерними объектами,
являющимися сущностями, а не типами значений (например, категориями и объектами, или родительскими
и дочерними кошками). У сущностей есть свой жизненный цикл и поддержка общих ссылок. Удаление
сущности из коллекции не означает, что она может быть удалена), и по умолчанию
нет каскадирования состояния от одной сущности к любым другим связанным сущностям. Hibernate
по умолчанию не реализует постоянство по повторному присоединению.

Для каждой базовой операции сессии Hibernate, включая persist(), merge(),
saveOrUpdate(), delete(), lock(), refresh(),
evict(), replicate() — существует соответствующий каскадный стиль. Соответственно,
каскадные стили называются create, merge, save-update, delete, lock, refresh, evict, replicate.
Если вы хотите, чтобы операция была каскадирована по ассоциации, вы должны указать это
в документе отображения. Например:

Каскадные стили можно сочетать:

Вы даже можете использовать cascade=«all», чтобы указать, что все операции должны
быть каскадированы вдоль ассоциации. По умолчанию cascade=«none» указывает,
что никакие операции не должны каскадироваться.

Если вы используете аннотации, вы, вероятно, заметили, что атрибут cascade принимает массив
CascadeType в качестве значения. Каскадная концепция в JPA очень похожа на переходное
постоянство (transitive persistence) и каскадирование операций, как описано выше, но с немного
отличающейся семантикой и каскадированием типов:

Заметка

Отображение ассоциации (либо однозначной ассоциации, либо коллекции) с cascade=«all»
помечает ассоциацию как отношение в стиле родитель/ребёнок, где сохранение, обновление или удаление
родительского объекта приводит к сохранению, обновлению или удалению дочернего объектов.

Кроме того, простая ссылка на ребенка из постоянного родителя приведет к сохранению/обновлению
дочернего объекта. Однако эта метафора неполна. Ребенок, который стал разыменованным от своего родителя,
автоматически не удаляется, за исключением случая ассоциации «один-ко-многим»,
отображаемой с помощью cascade=«delete-orphan». Точная семантика каскадных операций
для отношения родитель/ребёнок выглядит следующим образом:

Наконец, обратите внимание, что каскадирование операций может быть применено к графу объектов
во время вызова или во время сборса. Все операции, если они включены, каскадируются
на ассоциированные сущности, доступные при выполнении операции. Однако save-update
и delete-orphan являются транзитивными для всех ассоциированных сущностей, доступных
во время сессии.

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

Session session = sessionFactory.openSession();

2. Create a Native Query

Репликация объекта между двумя разными хранилищами данных

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

//получить Cat из одной базы данных
Session session1 = factory1.openSession();
Transaction tx1 = session1.beginTransaction();
Cat cat = session1.get(Cat.class, catId);
tx1.commit();
session1.close();
//согласовать со второй базой данных
Session session2 = factory2.openSession();
Transaction tx2 = session2.beginTransaction();
session2.replicate(cat, ReplicationMode. LATEST_VERSION);
tx2.commit();
session2.close();

Читайте также:  ГОСУДАРСТВЕННОЕ УЧРЕЖДЕНИЕ - ЛЕНИНГРАДСКОЕ РЕГИОНАЛЬНОЕ ОТДЕЛЕНИЕ ФОНДА СОЦИАЛЬНОГО СТРАХОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ - Группы в районах

ReplicationMode определяет, как replicate() будет иметь дело с конфликтами
с существующими записями в базе данных:

Случаи использования для этой функции включают сверку данных, введённых в разные экземпляры базы данных,
обновление информации о конфигурации системы во время обновления продукта, откатывание изменений,
сделанных во время транзакций, отличных от ACID, и многое другое.

Использование метаданных

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

Hibernate предоставляет метаданные через интерфейсы ClassMetadata
и CollectionMetadata и иерархию Type. Экземпляры интерфейсов метаданных можно
получить из SessionFactory.

Hibernate SQL Query

Hibernate provide option to execute native SQL queries through the use of SQLQuery object. Hibernate SQL Query is very handy when we have to execute database vendor specific queries that are not supported by Hibernate API. For example query hints or the CONNECT keyword in Oracle Database. For normal scenarios, Hibernate SQL query is not the recommended approach because we loose benefits related to hibernate association and hibernate first level cache. Я буду использовать базу данных MySQL и те же таблицы и настройки данных, что и в примере HQL, поэтому вам следует сначала проверить это, чтобы понять сопоставление таблиц и соответствующих классов модели.

Пример собственного SQL Hibernate

Для собственного SQL-запроса Hibernate мы используем Session.createSQLQuery(String query) для создания объекта SQLQuery и его выполнения. Например, если вы хотите прочитать все записи из таблицы «Сотрудники», мы можем сделать это с помощью кода ниже.

Обратите внимание, что наш запрос не возвращает данные адреса, тогда как если мы используем запрос HQL «от сотрудника», он также возвращает связанные данные таблицы.

SQL-запрос в спящем режиме addScalar

Hibernate использует ResultSetMetadata для определения типа столбцов, возвращаемых запросом. С точки зрения производительности мы можем использовать метод addScalar() для определения типа данных столбца. Однако мы все равно получим данные в виде массива объектов.

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

Несколько таблиц Hibernate Native SQL

Если мы хотим получить данные как из таблицы «Сотрудник», так и из таблицы «Адрес», мы можем просто написать для этого SQL-запрос и проанализировать набор результатов.

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

Hibernate Native SQL Entity и соединение

Мы также можем использовать методы addEntity() и addJoin() для извлечения данных из связанной таблицы с помощью соединения таблиц. Например, приведенные выше данные также можно получить, как показано ниже.

Читайте также:  Фсс воронеж личный кабинет вход через госуслуги

Вы можете запустить оба запроса в клиенте MySQL и заметить, что полученные результаты одинаковы.

Собственный SQL-запрос Hibernate с параметрами

Мы также можем передавать параметры в запросы SQL Hibernate, как и JDBC ReadedStatement. Параметры можно установить, используя имя, а также индекс, как показано в примере ниже.

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

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

Именованный запрос в спящем режиме

У нас есть файл отображения спящего режима, который содержит только именованные запросы HQL и именованные запросы Native SQL. именованные-queries.hbm.xml

Именованный запрос Hibernate @NamedQuery Аннотация

У нас есть два класса моделей — «Сотрудник» и «Адрес». Мы определили запросы имен в классе Address, как показано ниже.

Программа тестирования именованных запросов в Hibernate

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

Важные моменты по именованным запросам в Hibernate

Несколько важных моментов в отношении именованного запроса в Hibernate:

Это все, что касается примера именованного запроса в Hibernate. Вы можете скачать образец проекта по ссылке ниже.

Загрузить проект именованных запросов Hibernate

5. Закрыть сессию

String sqlQuery = «ВЫБРАТЬ * ИЗ клиентов WHERE last_name = :lastName»;

Запрос SQLQuery = session.createSQLQuery(sqlQuery);

3. Установите параметры

Сброс (flush) сессии

Иногда сеанс выполняет инструкцию SQL, настройку для синхронизации состояния соединений JDBC.
с состоянием предметов, хранящихся в памяти. Этот процесс, название сброса (flush),
происходит по умолчанию в следующих точках:

Операторы SQL выполняются в следующем порядке:

Исключением является то, что объекты, использующие встроенную генерацию идентификаторов,
в одиночестве при их сохране.

За исключением случаев, когда вы явно возникает флеш(), нет абсолютно никаких гарантий
о том, когда Session вызывает вызовы JDBC, — только тот порядок,
в котором они выполнили. Однако Hibernate гарантирует, что Query.list(.) никогда
не вернет конфиденциальность или неверные данные.

Можно изменить поведение по умолчанию, например, для сброса (сброса) бита реже. Класс FlushMode
Определите три разных режима: только сброс (flush) в момент фиксации (фиксация), когда используется
API транзакций Hibernate, сброс (сброс) автоматически используется в режиме ожидания или никогда.
не сбрасывается, если явно не вызывается функцияlush(). Последний режим был использован
для длительной работы, когда сессия остается открытой и отключается через
посещение времени (см.
раздел 13.3.2, «Расширенная сессия и автоматическое ведение управления»).

Во время сброса (flush) может возникнуть исключение (например, если операция DML нарушает ограничение).
Поскольку обработка исключений предполагает некоторое понимание поведения транзакционний Hibernate,
мы обсуждаем его в главе 13 «Транзакции и параллельное выполнение».

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