正如链接的作者在下面所说:
我目前正在开发一个需要在数据库中进行软删除的Seam应用程序。在右侧,您可以看到我的数据库关系图的一个片段,其中包含一个和表。这只是一个直截了当的关系,但重要的是要注意每个表中的“已删除”字段。这是将用于跟踪软删除的字段。如果字段包含“1”,则记录已被删除,如果包含“0”,则记录尚未删除。CUSTOMER
APP_USER
在像Hibernate这样的ORM之前,我必须使用SQL自己跟踪和设置这个标志。这并不难做到,但谁想写一堆样板代码只是为了跟踪记录是否被删除。这就是Hibernate和注释来拯救的地方。
以下是 Hibernate 使用 seamgen 生成的 2 个实体类。为了清楚起见,我省略了部分代码。
客户.java
//Package name...
//Imports...
@Entity
@Table(name = "CUSTOMER")
//Override the default Hibernation delete and set the deleted flag rather than deleting the record from the db.
@SQLDelete(sql="UPDATE customer SET deleted = '1' WHERE id = ?")
//Filter added to retrieve only records that have not been soft deleted.
@Where(clause="deleted <> '1'")
public class Customer implements java.io.Serializable {
private long id;
private Billing billing;
private String name;
private String address;
private String zipCode;
private String city;
private String state;
private String notes;
private char enabled;
private char deleted;
private Set appUsers = new HashSet(0);
// Constructors...
// Getters and Setters...
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "customer")
// Filter added to retrieve only records that have not been soft deleted.
@Where(clause = "deleted <> '1'")
public Set getAppUsers() {
return this.appUsers;
}
public void setAppUsers(Set appUsers) {
this.appUsers = appUsers;
}
}
应用用户.java
//Package name...
//Imports...
@Entity
@Table(name = "APP_USER")
//Override the default Hibernation delete and set the deleted flag rather than deleting the record from the db.
@SQLDelete(sql="UPDATE app_user SET deleted = '1' WHERE id = ?")
//Filter added to retrieve only records that have not been soft deleted.
@Where(clause="deleted <> '1'")
public class AppUser implements java.io.Serializable {
private long id;
private Customer customer;
private AppRole appRole;
private char enabled;
private String username;
private String appPassword;
private Date expirationDate;
private String firstName;
private String lastName;
private String email;
private String phone;
private String fax;
private char deleted;
private Set persons = new HashSet(0);
// Constructors...
// Getters and Setters...
}
以下2个步骤是实现软删除所要做的。
- 添加了注释,该注释将覆盖该实体的默认休眠删除。
@SQLDelete
- 添加了注释以筛选查询并仅返回尚未软删除的记录。另请注意,在 CUSTOMER 类中,我向 appUsers 集合添加了 。这是仅获取该客户的尚未软删除的应用程序用户所必需的。
@Where
@Where
中提琴!现在,每当您删除这些实体时,它都会将“已删除”字段设置为“1”,当您查询这些实体时,它将仅返回在“已删除”字段中包含“0”的记录。
难以置信,但这就是使用Hibernate注释实现软删除的全部内容。
注意:
另请注意,您可以使用休眠过滤器(http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-filters)全局过滤掉所有“已删除”实体,而不是使用语句。我发现定义2个实体管理器(“正常”一个过滤已删除的项目,一个不过滤已删除的项目,对于极少数情况......)通常非常方便。@Where(clause="deleted ‘1’")
使用实体用户
您可以创建例如:DeleteEventListener
public class SoftDeleteEventListener extends DefaultDeleteEventListener {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void onDelete(DeleteEvent event, Set arg1) throws HibernateException {
Object o = event.getObject();
if (o instanceof SoftDeletable) {
((SoftDeletable)o).setStatusId(1);
EntityPersister persister = event.getSession().getEntityPersister( event.getEntityName(), o);
EntityEntry entityEntry = event.getSession().getPersistenceContext().getEntry(o);
cascadeBeforeDelete(event.getSession(), persister, o, entityEntry, arg1);
cascadeAfterDelete(event.getSession(), persister, o, arg1);
} else {
super.onDelete(event, arg1);
}
}
}
把它钩到你的坚持中.xml就像这样
<property name = "hibernate.ejb.event.delete" value = "org.something.SoftDeleteEventListener"/>
另外,不要忘记在注释中更新级联。
资源链接:
- 休眠:使用继承覆盖 sql 删除
- 用于 CRUD 操作的自定义 SQL
- 用于创建、更新和删除的自定义 SQL