Удаление с помощью метода remove()

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

  • Удаление с помощью метода remove()
  • Удаление за компанию
  • Удаление по Orphan
  • Удаление с помощью JPQL
  • Удаление через NativeQuery
  • softDeleted()

И начнем мы с самого очевидного решения — вызова метода remove().


User user = new User();
user.setName("Колян");
session.persist(user);  //добавляем объект в базу
session.flush(); 
session.clear();  //закрываем сессию
 
user = (User) session.find(User.class, user.getId() ); //заново получаем объект из базы
session.remove(user);
session.flush(); 
session.clear();  //закрываем сессию
 
//тут объект реально удален.

Реальная операция в базе будет выполнена после вызова метода flush() или закрытия транзакции.

Каскадное удаление

Помнишь, когда мы изучали SQL, то зависимым таблицам можно было прописывать CONSTRAINT. И одна из них записывалась так:


CONSTRAINT ONDELETE REMOVE

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

Допустим, мы где-то храним персональную информацию пользователя и настроили CONSTRAINT в базе так, чтобы при удалении пользователя эти данные тоже удалялись. Тогда нам нужно просто удалить родительский объект и все дочерние объекты будут удалены на уровне базы:


User user = new User();
UserPrivateInfo info = new UserPrivateInfo();
user.setPrivateInfo(info);
session.persist(user);  //добавляем объект в базу, также в базу сохранится и объект info
session.flush(); 
session.clear();  //закрываем сессию
 
user = (User) session.find(User.class, user.getId() ); //заново получаем объект из базы
session.remove(user);
session.flush(); 
session.clear();  //закрываем сессию
 
//тут объекты user и info реально удалены из базы.

Удаление по Orphan

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

Допустим, у нас есть пользователь, а у него есть список сообщений:


User user = new User();
UserMessage message = new UserMessage();
user.getMessageList().add(message);
session.persist(user);  //добавляем объект в базу, также в базу сохранится и объект message
session.flush(); 
session.clear();  //закрываем сессию
 
user = (User) session.find(User.class, user.getId() ); //заново получаем объект из базы
UserMessage message2 = user.getMessageList().get(0); //получаем сообщение пользователя
user.getMessageList().remove(message2);  //удаляем сообщение из списка
session.flush(); 
session.clear();  //закрываем сессию
 
//тут объект message2 реально удален из базы

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


@Entity
public class User {
 
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List<UserMessage> messageList = new ArrayList<UserMessage>();
 
}

Удаление через JPQL

Еще один интересный способ удалить объект – это написать запрос на HQL (или JPQL). Только не забудь в конце вызвать метод executeUpdate(), а не то Hibernate создает read-only транзакцию и никакого удаления у тебя не выйдет.

Пример:


User user = new User();
session.persist(user);  //добавляем объект в базу
session.flush(); 
session.clear();  //закрываем сессию
 
session.createQuery("delete from User where id = :id")
   .setParameter("id", user.getId())
   .executeUpdate();

Изменение в базе никак не изменит существующие Entity-объекты.

Удаление через NativeQuery

Аналогично можно удалить и через вызов NativeQuery.

Пример:


User user = new User();
session.persist(user);  //добавляем объект в базу
session.flush(); 
session.clear();  //закрываем сессию
 
session.createNativeQuery("DELETE FROM user WHERE id = :id")
   .setParameter("id", user.getId())
   .executeUpdate();

Изменение в базе никак не затронет существующие Entity-объекты.

Мягкое удаление

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

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

Поэтому создатели Hibernate придумали специальную аннотацию, с помощью которой можно было бы помечать объекты как живые. Пример:


@Entity
@Where(clause = "DELETED = 0") //во всех WHERE будет добавляться “AND DELETED = 0”
public class User {
	// маппинг полей
 
	@Column(name = "DELETED") // если значение в колонке DELETED == 0, то запись жива, если 1 - мертва
	private Integer deleted = 0; 
   
	//геттеры и сеттеры
 
    public void softDeleted() {
    	this.deleted = 1; //помечаем запись как мертвую
    }
}

Чтобы пометить объект как удаленный нужно просто вызвать у него метод softDeleted():


User user = new User();
session.persist(user);  //добавляем объект в базу
session.flush(); 
session.clear();  //закрываем сессию
 
user = (User) session.find(User.class, user.getId() ); //заново получаем объект из базы
user.softDeleted(); //помечаем объект как удаленный
session.flush(); 
session.clear();  //закрываем сессию
 
//больше этот объект не будет находиться через Hibernate
undefined
1
Задача
Модуль 4. Работа с БД, 11 уровень, 4 лекция
Недоступна
task1104
Напиши код удаления объекта animalRemove с помощью метода remove(). Запусти программу и убедись, что до удаления объект не был равен null, а после удаления — равен null...
undefined
1
Задача
Модуль 4. Работа с БД, 11 уровень, 4 лекция
Недоступна
task1105
Напиши код удаления объекта типа Animal c id = 2 с помощью HQL. Используй методы createQuery() и executeUpdate()...