【发布时间】:2015-06-30 07:14:19
【问题描述】:
我需要为我的应用程序管理的所有实体添加 软删除 功能。为了实现这一点,我创建了一个带有 deleted 字段的基实体类(MappedSuperclass),如下所示:
@MappedSuperclass
public abstract class BaseVersionableEntity {
@Id
@Basic(optional = false)
@NotNull
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", nullable = false)
protected Long id;
@Version
@Column(name = "VERSION", nullable = false)
protected Long version;
@Basic
@Column(name = "DELETED")
protected boolean deleted;
public boolean isDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
// equals/hashCode
}
通过使用 hibernate 的 interceptor 机制,我配置了一个 软删除拦截器 以捕获 hibernate 执行的所有查询:
public class SoftSelectInterceptor extends EmptyInterceptor{
private static final long serialVersionUID = 1L;
@Override
public String onPrepareStatement(String sql) {
if(sql.startsWith("select")){
sql = sql.replace("where ","where deleted=0 and ");
}
return super.onPrepareStatement(sql);
}
}
我在 persistence.xml 文件中添加了以下拦截器配置
<property name="hibernate.ejb.interceptor" value="com.my.organization.SoftSelectInterceptor"/>
请注意,还有一个 SoftDeleteInterceptor。以同样的方式工作。
当我执行此代码时,hibernate 会在 onPerparedStatement 方法中捕获 select 语句调用,但它会在表字段前添加表别名。也就是说如果表名是reportTemplate,hibernate给这个表reportTemplate0别名。所以我的替换语句需要如下所示:
sql = sql.replace("where ","where reportTemplate0.deleted=0 and ");
我可以解析 sql 字符串并尝试推断正确的表别名。但是在复杂的 sql 语句中(当同一个实体被多次使用时)很难推断。
我想知道是否有更好的方法来做到这一点。
【问题讨论】: