JavaRush /Курсы /Модуль 4. Работа с БД /Работа с Entity-объектами

Работа с Entity-объектами

Модуль 4. Работа с БД
9 уровень , 3 лекция
Открыта

4.1 Транзакции и целостность базы данных

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

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

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

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

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

Любой современный SQL-сервер позволяет изменять данные только в транзакциях. Ты открываешь транзакцию, вносишь любые изменения в любое количество таблиц, и комитишь транзакцию. Затем SQL-сервер пробует внести изменения. Если все просто хорошо, то они добавятся к общей базе данных. Если были проблемы, то все изменения отменятся.

Hibernate тоже использует эту парадигму. Именно поэтому в предыдущей лекции мы увидели, что при попытке сохранить объект Employee в базу сначала открывалась транзакция, а после сохранения – коммитилась.

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

4.2 Получение объектов

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

Мы же с тобой разберем способы работы с базой данных. И самый простой из них — это получение объекта по его ID. Для этого нужно использовать метод get() у объекта session. Общий вид такого запроса:


Класс имя = session.get(Класс.class, ID);
        

Пример:


public User getUserById(Integer id) {
    try (Session session = sessionFactory.openSession()) {
        User user = session.get(User.class, id);
        return user;
    }
}

4.3 Сохранение (добавление) объектов

Если ты хочешь сохранить свой объект в базу данных, то на уровне SQL будет выполнен запрос INSERT. Поэтому твои действия нужно выполнять в виде отдельной транзакции. Кроме того, для сохранения лучше использовать метод persist() объекта session.

Общий вид такого запроса:


session.persist(Объект);
        

Метод persist() меняет не только базу, но и сам объект. Все дело в том, что когда мы добавляем объект в базу, то до добавления у этого объекта еще нет своего ID. Ну, обычно так, хотя бывают нюансы. А после добавления у объекта ID уж есть.


public boolean saveUser(User user) {
    try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
            session.persist(user);
            transaction.commit();
            return true;
    }
    catch() {
    return false;
   	}
}

Также у объекта Session есть метод save(), который выполняет аналогичную функцию. Просто метод save() — это старый стандарт Hibernate, а метод persist() — это JPA-стандарт.

4.4 Удаление объектов

Если вы хотите удалить существующей объект, то сделать это очень просто. Для этого у объекта session есть специальный метод — remove().

Общий вид такого запроса:


session.remove(Объект);
        

И, конечно же, напишем код с примером:


public boolean removeUser(User user) {
    try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
            session.remove(user);
            transaction.commit();
            return true;
    }
    catch() {
    return false;
   	}
}

Зачем так сложно, спросишь ты?

Ну, во-первых, любые изменения базы данных всегда несут за собой различные и не всегда очевидные последствия. А во-вторых, у данного объекта могли быть связанные с ним дочерние объекты и т. п. Так что сценарии удаления часто бывают нетривиальными.

1
Задача
Модуль 4. Работа с БД, 9 уровень, 3 лекция
Недоступна
task0905
Если ранее не подключал зависимости, то подключи их. Для этого используй Alt + Ctrl + Shift + S (в Идее), вкладка Libraries...
Комментарии (7)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Arseniy Rigin Уровень 1 Expert
4 августа 2024
без catch принимает
Kirill Уровень 106 Expert
1 августа 2024
Обязательно ли делать через ссылку на транзакцию как в примере или же можно обращаться к транзакции через сессию?

            session.beginTransaction();
            session.remove(animal);
            session.getTransaction().commit();
Кстати этот вариант валидатор не пропускает
Михаил Уровень 111 Expert
11 ноября 2023
обязательно transaction.commit();
Anonymous #3272489 Уровень 92 Expert
26 сентября 2023
задача поему-то с persist не проходит, только save 😑
Эльдар Уровень 108 Expert
1 октября 2023
Может исправили, у меня прошло
Anonymous #3328237 Уровень 2
19 апреля 2024
У меня тоже не проходила, я убрал из объекта id, всё заработало
Dmitry Fokin Уровень 51
15 мая 2023
хорошая лекция