I need to add soft delete feature for all entities that my application manages. In order to accomplish that I created a base entity class(MappedSuperclass) with deleted field as below:
@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
}
By using hibernate's interceptor mechanism I configured a soft delete interceptor in order to catch all queries that hibernate executes:
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);
}
}
I added below interceptor config to persistence.xml file
<property name="hibernate.ejb.interceptor" value="com.my.organization.SoftSelectInterceptor"/>
Note that there is a SoftDeleteInterceptor as well. Works with the same way.
When I execute this code hibernate catches select statement calls in onPeraparedStatement method but it adds a table alias in front of the table fields. That is if table name is reportTemplate, hibernate give this table reportTemplate0 alias. So my replace statement needs to be like below:
sql = sql.replace("where ","where reportTemplate0.deleted=0 and ");
I can parse the sql string and try to infer correct table aliases. However in complex sql statements (when same entity used multiple times) it would be hard to infer.
I wonder if there is a better way to do this.