Hibernate 中的 @SoftDelete 註解指南
1. 概述
在應用程式中使用資料庫時,我們通常必須刪除不再有用的記錄。但是,由於業務或監管要求,例如資料恢復、審計追蹤或引用完整性目的,我們可能需要隱藏這些記錄而不是刪除它們。
在本教程中,我們將了解 Hibernate 中的@SoftDelete
註釋並了解如何實現它。
2. 理解@SoftDelete
註解
@SoftDelete
註釋提供了一種方便的機制來將任何記錄標記為活動或已刪除。它有三個不同的配置部分:
- 此策略配置是否追蹤活動的行或已刪除的行。我們可以透過將
strategy
設定為ACTIVE
或DELETED
來設定它 - 指示符列標識將使用哪一列來追蹤行。如果沒有指定列,則策略將使用預設列(
active
或deleted
)。 - 轉換器定義指標列在資料庫中的設定方式。域類型是一個
boolean
值,指示記錄是活動的還是已刪除的。但是,透過實作AttributeConverter
,我們可以將關係類型設定為轉換器定義的任何類型。可用的轉換器有NumericBooleanConverter
、YesNoConverter
和TrueFalseConverter.
3. 實現@SoftDelete
讓我們來看幾個範例,了解如何透過不同的配置使用@SoftDelete
。
3.1.楷模
讓我們定義一個實體類別SoftDeletePerson
,並用@SoftDelete
來註解。我們不提供任何額外的配置,註解採用所有預設值,例如DELETED
策略、 deleted
指標列、儲存為boolean
類型。
@SoftDelete
註解支援@ElementCollection
,我們已將其配置策略定義為ACTIVE
、預設指示符列,並使用YesNoConverter
儲存為'Y'
或'N'
:
@SoftDelete
public class SoftDeletePerson {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String name;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "Emails", joinColumns = @JoinColumn(name = "id"))
@Column(name = "emailId")
@SoftDelete(strategy = SoftDeleteType.ACTIVE,converter = YesNoConverter.class)
private List<String> emailIds;
// standard getters and setters
}
3.2.數據設定
讓我們為SoftDeletePerson
實體建立幾個資料庫條目,看看 Hibernate 如何將它們保存在資料庫中:
@BeforeEach
public void setup() {
session = sessionFactory.openSession();
session.beginTransaction();
SoftDeletePerson person1 = new SoftDeletePerson();
person1.setName("Person1");
List<String> emailIds = new ArrayList<>();
emailIds.add("[email protected]");
emailIds.add("[email protected]");
person1.setEmailIds(emailIds);
SoftDeletePerson person2 = new SoftDeletePerson();
person2.setName("Person2");
List<String> emailIdsPerson2 = new ArrayList<>();
emailIdsPerson2.add("[email protected]");
emailIdsPerson2.add("[email protected]");
person2.setEmailIds(emailIdsPerson2);
session.save(person1);
session.save(person2);
session.getTransaction()
.commit();
assertNotNull(person1.getName());
assertNotNull(person2.getName());
System.out.println(person1);
System.out.println(person2);
}
在上面的測試案例中,我們保存了兩個SoftDeletePerson
實體並列印了相同的實體以視覺化資料庫中儲存的內容。下面的輸出顯示 Hibernate 儲存SoftDeletePerson
並將deleted
欄位設定為false
。此外,集合emailIds
active
列設定為值'Y':
3.3.測試
在上一步中,我們在資料庫中保留了幾行。現在,讓我們看看@SoftDelete
如何處理記錄的刪除:
@Test
void whenDeletingUsingSoftDelete_ThenEntityAndCollectionAreDeleted() {
session.beginTransaction();
person1 = session.createQuery("from SoftDeletePerson where name='Person1'", SoftDeletePerson.class)
.getSingleResult();
person2 = session.createQuery("from SoftDeletePerson where name='Person2'", SoftDeletePerson.class)
.getSingleResult();
assertNotNull(person1);
assertNotNull(person2);
session.delete(person2);
List<String> emailIds = person1.getEmailIds();
emailIds.remove(0);
person1.setEmailIds(emailIds);
session.save(person1);
session.getTransaction()
.commit();
List<SoftDeletePerson> activeRows = session.createQuery("from SoftDeletePerson")
.list();
List<SoftDeletePerson> deletedRows = session.createNamedQuery("getDeletedPerson", SoftDeletePerson.class)
.getResultList();
session.close();
assertNotNull(person1.getName());
System.out.println("-------------Active Rows-----------");
activeRows.forEach(row -> System.out.println(row));
System.out.println("-------------Deleted Rows-----------");
deletedRows.forEach(row -> System.out.println(row));
}
首先,我們從資料庫中取得現有行。接下來,我們刪除了其中一個實體,同時更新了另一個emailIds.
然後,當我們刪除SoftDeletePerson
實體之一時,Hibernate 會設定deleted=true
。類似地,當我們刪除其中一個電子郵件 ID 時,Hibernate 將前面的行設為active='N'
,並插入帶有active='Y'
新行。
最後,當我們取得活動行和刪除行時,我們可以看到預期的結果:
4。結論
在本文中,我們探討了 Hibernate 中@SoftDelete
註解的實作。預設配置採用DELETED
策略,並以boolean
值儲存在資料庫列deleted
中。
我們也了解了該註釋如何支援@ElementCollection
。最後,我們透過不同配置的測試案例驗證了結果。
與往常一樣,所有範例的原始程式碼都可以在 GitHub 上找到。