使用 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
GO TO FULL VERSION