I have some entities. For example
@Entity
@IdClass(SecurityUserPublisherId.class)
@Table(name="SECUSERPUB")
public class SecurityUserPublisher extends Auditable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="USERPUB_CONTACTID", updatable=false, nullable=false)
protected Integer contactId = null;
@Id
@Column(name="USERPUB_PUBID", updatable=false, nullable=false)
protected Integer publisherId = null;
public SecurityUserPublisher() {
super();
setAudited(true);
}
public SecurityUserPublisher(SecurityUserPublisher securityUserPublisher) {
setContactId(securityUserPublisher.getContactId());
setPublisherId(securityUserPublisher.getPublisherId());
}
public Integer getContactId() {return contactId;}
public void setContactId(Integer contactId) {this.contactId = contactId;}
public Integer getPublisherId() {return publisherId;}
public void setPublisherId(Integer publisherId) {this.publisherId = publisherId;}
@Transient
@Override
public String getPrimaryKeyDisplay() {
StringBuilder sb = new StringBuilder();
if (contactId == null) {
sb.append(" contactId: null");
} else {
sb.append(" contactId: " + contactId.toString());
}
if (publisherId == null) {
sb.append(" publisherId: null");
} else {
sb.append(" publisherId: " + publisherId.toString());
}
return sb.toString();
}
@Transient
@Override
public String getAuditDetail() {
return new ToStringBuilder(this).append("contactId", contactId).append("publisherId", publisherId).toString();
}
}
They extend the Auditable class
public abstract class Auditable implements Serializable {
private static final long serialVersionUID = 1L;
protected Integer auditContactId = null;
protected Boolean audited = false;
public void setAuditContactId(Integer auditContactId) {this.auditContactId = auditContactId;}
public Integer getAuditContactId() {return auditContactId;}
public Boolean isAudited() {return audited;}
protected void setAudited(Boolean audited) {this.audited = audited;}
public abstract String getPrimaryKeyDisplay();
public abstract String getAuditDetail();
}
And I have an interceptor
public class AuditInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 1L;
private Set<Auditable> inserts = new HashSet<>();
private Set<Auditable> updates = new HashSet<>();
private Set<Auditable> deletes = new HashSet<>();
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
throws CallbackException {
if (entity != null && entity instanceof Auditable && ((Auditable)entity).isAudited()){
System.out.println(entity.toString());
System.out.println(id.toString());
System.out.println(Arrays.toString(state));
System.out.println(Arrays.toString(propertyNames));
System.out.println(Arrays.toString(types));
inserts.add((Auditable)entity);
}
return super.onSave(entity, id, state, propertyNames, types);
}
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)
throws CallbackException {
if (entity instanceof Auditable && ((Auditable)entity).isAudited()){
updates.add((Auditable)entity);
}
return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}
@Override
public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
if (entity instanceof Auditable && ((Auditable)entity).isAudited()){
System.out.println(entity.toString());
System.out.println(id.toString());
System.out.println(Arrays.toString(state));
System.out.println(Arrays.toString(propertyNames));
System.out.println(Arrays.toString(types));
deletes.add((Auditable)entity);
}
}
//called before commit into database
@Override
public void preFlush(@SuppressWarnings("rawtypes") Iterator iterator) {
}
//called after committed into database
@Override
public void postFlush(@SuppressWarnings("rawtypes") Iterator iterator) {
try {
for (Iterator<Auditable> iter = inserts.iterator(); iter.hasNext();) {
Auditable entity = iter.next();
iter.remove();
logIt("Saved", entity);
}
for (Iterator<Auditable> iter = updates.iterator(); iter.hasNext();) {
Auditable entity = iter.next();
iter.remove();
logIt("Updated", entity);
}
for (Iterator<Auditable> iter = deletes.iterator(); iter.hasNext();) {
Auditable entity = iter.next();
iter.remove();
logIt("Deleted", entity);
}
} finally {
inserts.clear();
updates.clear();
deletes.clear();
}
}
public void logIt(String action, Auditable entity) {
if (!entity.isAudited()) {
return;
}
Session tempSession = SessionHelper.getSession().getSession().getSessionFactory().openSession();
Audit auditRecord = new Audit();
auditRecord.setAction(action);
auditRecord.setContactId(entity.getAuditContactId());
auditRecord.setDetail(entity.getAuditDetail());
auditRecord.setCreatedTimestamp(new Timestamp(System.currentTimeMillis()));
auditRecord.setEntityPK(entity.getPrimaryKeyDisplay());
auditRecord.setEntityName(entity.getClass().toString());
tempSession.save(auditRecord);
tempSession.flush();
}
}
I can create entities
final SecurityUserPublisher secUserPub = new SecurityUserPublisher();
secUserPub.setContactId(currentUser.getContactId());
secUserPub.setPublisherId(publisher.getId());
secUserPub.setAuditContactId(parentFrame.getUser().getContactId());
try {
SessionHelper.getCreate().createSecurityUserPublisher(secUserPub);
and the audit trail looks good
AUDIT_ID 120385
AUDIT_ACTION Saved
AUDIT_DETAIL SecurityUserPublisher@678541a[contactId=8721,publisherId=360] AUDIT_CREATEDTS 2019-04-04 13:52:57
AUDIT_ENTITYPK contactId: 8721 publisherId: 360
AUDIT_ENTITYNAME SecurityUserPublisher
AUDIT_CONTACTID 7341
But when I try to delete
final SecurityUserPublisher secUserPub = SessionHelper.getSession().getSecurityUserPublisher(currentUser.getContactId(), publisher.getId());
secUserPub.setAuditContactId(parentFrame.getUser().getContactId());
try {
SessionHelper.getRemove().removeSecurityUserPublisher(secUserPub);
the audit trail contact id is null, even though I expressly set it before calling the remove.
AUDIT_ID 120386
AUDIT_ACTION Deleted
AUDIT_DETAIL SecurityUserPublisher@1d184bc8[contactId=8721,publisherId=360]
AUDIT_CREATEDTS 2019-04-04 13:53:35
AUDIT_ENTITYPK contactId: 8721 publisherId: 360
AUDIT_ENTITYNAME SecurityUserPublisher
AUDIT_CONTACTID null
So, how do I get the onDelete to show the contactId in the Audit table?
Advertisement
Answer
Use @MappedSuperclass annotation on Auditable class. Otherwise Hibernate ignores super class fields and fields of Auditable class are not saved into DB.