I have a working ENVERs project that I was finalizing the implementation and noticed the property level modification tracking feature. This feature sounds perfect for our needs and would replace a few (manual) tables.
The problem comes in here; I have the fields set in the database, but they are not being updated by ENVERs when I change things such as the the status column.
Table;
DROP TABLE IF EXISTS `enrollment_history` ;
CREATE TABLE `enrollment_history` (
`revision` INTEGER NOT NULL,
`revision_type` INTEGER NOT NULL,
`enrollment_id` BIGINT(20) NOT NULL,
`enrollment_status_id` BIGINT(20) NOT NULL,
`enrollment_status_id_modified` boolean NOT NULL default 0,
PRIMARY KEY USING BTREE (`enrollment_id`, `revision`))
ENGINE=INNODB;
POJO:
@Entity
@Table(name = "enrollment")
@Audited(withModifiedFlag = true)
public class Enrollment implements Serializable {
//...
@Column(name = "enrollment_status_id", nullable = false)
@NotNull
@Enumerated(EnumType.ORDINAL)
@Audited(modifiedColumnName = "enrollment_status_id_modified")
private EnrollmentStatus status;
// getters setters etc
//...
}
DAO
public class DAO {
@Autowired
private SessionFactory sessionFactory;
public AuditReader getAuditReader() {
return AuditReaderFactory.get(sessionFactory.getCurrentSession());
}
@SuppressWarnings("unchecked")
@Override
public List<Enrollment> getEnrollmentsWhereStatusIsChanged(long userId) {
AuditReader reader = getAuditReader();
List<Enrollment> specificChanges =
//@formatter:off
reader
.createQuery()
.forRevisionsOfEntity(Enrollment.class, true, true)
.add(AuditEntity.id().eq(userId))
.add(AuditEntity.property("status").hasChanged())
.getResultList();
//@formatter:on
return specificChanges;
}
}
Any guidance into what I am missing would be great. It almost seems as if Envers is aware of the fields since it is no longer complaining about the mappings, but at runtime it is missing something to fill them in or read data from them.
This is the error I receive at runtime;
org.hibernate.QueryException: could not resolve property: status_modified of: com.intellimec.drivesync.database.entity.enrollment.Enrollment_history
****EDIT**** We are using Hibernate 4.3.11.Final
The root cause of this is that I had the global "org.hibernate.envers.global_with_modified_flag" set to false and there is a bug in the framework where IF this value is set, it cannot be override, unlike other global configrations. I have logged HHH-10468 for this issue.
Another caveat, the withModifiedFlag (and the modifiedColumnName) attributes of the @Audited annotation do absolutely nothing when specified at the class level. I have logged HHH-10469 for this issue.
To work around these issues I have removed the global setting from being supplied since it cannot be overridden and changed my POJO to look like this;
@Entity
@Table(name = "enrollment")
@Audited
public class Enrollment implements Serializable {
//...
@Column(name = "enrollment_status_id", nullable = false)
@NotNull
@Enumerated(EnumType.ORDINAL)
@Audited(withModifiedFlag = true, modifiedColumnName = "enrollment_status_id_modified")
private EnrollmentStatus status;
// getters setters etc
//...
}
Hope this helps anyone else that gets caught up on this.