Премахване с метода remove().

И накрая, нека да разгледаме изтриването на обект. По принцип изтриването на обекти от базата данни е много просто, но Howто се казва, има нюанси. И има шест такива нюанса:

  • Премахване с метода remove().
  • Премахване за фирмата
  • Премахване от Orphan
  • Изтриване с JPQL
  • Изтриване чрез NativeQuery
  • softDeleted()

И ще започнем с най-очевидното решение – извикването на метода remove() .

User user = new User();
user.setName("Kolyan");
session.persist(user);  // add an object to the database
session.flush();
session.clear();  // close the session

user = (User) session.find(User.class, user.getId() ); //receive the object from the database
session.remove(user);
session.flush();
session.clear();  // close the session

//here the object is actually deleted.

Действителната операция в базата данни ще бъде изпълнена, след като методът flush() бъде извикан or транзакцията бъде затворена.

Каскадно изтриване

Спомняте ли си, когато изучавахме SQL, зависимите таблици можеха да бъдат написани с CONSTRAINT. И един от тях беше така:

CONSTRAINT ONDELETE REMOVE

Значението му беше, че ако имаме table, която съдържа дъщерни обекти, тогава, когато родителският обект бъде разпределен, всичките му деца трябва да бъдат изтрити.

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

User user = new User();
UserPrivateInfo info = new UserPrivateInfo();
user.setPrivateInfo(info);
session.persist(user);  //add the object to the database, the info object will also be saved to the database
session.flush();
session.clear();  // close the session

user = (User) session.find(User.class, user.getId() ); //receive the object from the database
session.remove(user);
session.flush();
session.clear();  // close the session

// here the user and info objects are actually removed from the database.

Премахване от Orphan

Има и друг вид премахване, наречено Orphan премахване. Донякъде е подобен на предишната version. Дъщерен обект се изтрива, когато връзката му с родителския обект е прекъсната. В този случай родителският обект обикновено не се изтрива.

Да приемем, че имаме потребител и той има списък с публикации:

User user = new User();
UserMessage message = new UserMessage();
user.getMessageList().add(message);
session.persist(user);  //add the object to the database, the message object will also be saved to the database
session.flush();
session.clear();  // close the session

user = (User) session.find(User.class, user.getId() ); //receive the object from the database
UserMessage message2 = user.getMessageList().get(0); //get the user's message
user.getMessageList().remove(message2);  //remove the message from the list
session.flush();
session.clear();  // close the session

// here the message2 object is actually removed from the database

Има и важен нюанс, ако искаме Hibernate да приложи това поведение, то трябва да бъде изрично указано при свързване на два обекта с помощта на анотации:

@Entity
public class User {

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List<UserMessage> messageList = new ArrayList<UserMessage>();

}

Изтриване чрез JPQL

Друг интересен начин за изтриване на обект е да напишете HQL (or JPQL) заявка. Само не забравяйте да извикате метода executeUpdate() в края , в противен случай Hibernate създава транзакция само за четене и няма да получите изтриване.

Пример:

User user = new User();
session.persist(user);  // add an object to the database
session.flush();
session.clear();  // close the session

session.createQuery("delete from User where id = :id")
   .setParameter("id", user.getId())
   .executeUpdate();

Промяната на базата данни няма да промени съществуващите обекти на Entity по ниHowъв начин.

Изтриване чрез NativeQuery

По същия начин можете да изтриете и извикате NativeQuery.

Пример:

User user = new User();
session.persist(user);  // add an object to the database
session.flush();
session.clear();  // close the session

session.createNativeQuery("DELETE FROM user WHERE id = :id")
   .setParameter("id", user.getId())
   .executeUpdate();

Промяната в базата данни няма да засегне по ниHowъв начин съществуващите обекти на Entity.

Меко изтриване

Понякога, instead of да изтривате данни в базата данни, е удобно просто да ги маркирате като изтрити. След това такива данни могат да участват в различни сценарии. Първо, такова изтриване е лесно обратимо - линиите могат отново да бъдат маркирани като живи.

Второ, полезно е да се „архивират“ такива отдалечени данни, защото има случаи, когато поведението на сървъра е регламентирано от закона и други подобни. Ако обаче маркирате данните си като изтрити, тогава само вие ще знаете, че са бor изтрити. Hibernate пак ще намери тези данни и ще ги използва при сортиране.

Затова създателите на Hibernate излязоха със специална анотация, с която би било възможно да се маркират обекти като живи. Пример:

@Entity
@Where(clause = "DELETED = 0") //in all WHEREs "AND DELETED = 0" will be added
public class User {
	// mapping fields

	@Column(name = "DELETED") // if the value in the DELETED column == 0, then the record is alive, if 1 - dead
	private Integer deleted = 0;

	//getters and setters

    public void softDeleted() {
    	this.deleted = 1; //mark the post as dead
    }
}

За да маркирате обект като изтрит, трябва само да извикате метода softDeleted() върху него :

User user = new User();
session.persist(user);  // add an object to the database
session.flush();
session.clear();  // close the session

user = (User) session.find(User.class, user.getId() ); //receive the object from the database
user.softDeleted(); // mark the object as deleted
session.flush();
session.clear();  // close the session

//this object will no longer reside via Hibernate