使用 remove() 方法刪除

最後,讓我們看看刪除一個對象。原則上,從數據庫中刪除對象非常簡單,但正如他們所說,存在細微差別。有六個這樣的細微差別:

  • 使用remove()方法刪除
  • 為公司除名
  • 被孤兒移除
  • 使用 JPQL 刪除
  • 通過 NativeQuery 刪除
  • 軟刪除()

我們將從最明顯的解決方案開始——調用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()方法或關閉事務後,才會執行數據庫中的實際操作。

級聯刪除

大家還記得我們學SQL的時候,依賴表是可以用CONSTRAINT來寫的。其中一個是這樣的:

CONSTRAINT ONDELETE REMOVE

它的意思是,如果我們有一個包含子實體的表,那麼當分配父實體時,必須刪除它的所有子實體。

假設我們把用戶的個人信息存放在某個地方,並在數據庫中設置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.

被孤兒移除

還有另一種類型的移除稱為孤兒移除。它與以前的版本有些相似。當子實體與父實體的關係中斷時,子實體將被刪除。在這種情況下,通常不會刪除父實體。

假設我們有一個用戶,他有一個帖子列表:

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(或 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();

更改數據庫不會以任何方式更改現有的實體對象。

通過 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();

數據庫中的更改不會以任何方式影響現有的實體對象。

軟刪除

有時,不是刪除數據庫中的數據,而是簡單地將其標記為已刪除會很方便。然後,這些數據可以參與各種場景。首先,這樣的刪除很容易恢復——這些行可以再次被標記為活動的。

其次,“存檔”此類遠程數據很有用,因為在某些情況下,服務器的行為受到法律等的監管。但是,如果您將數據標記為已刪除,那麼只有您知道它已被刪除。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