Search code examples
javahibernatehibernate-envers

For each save (update) hibernate envers creating revisions either changed in table or not


In my client server application, I am using JavaFx as client and Java hibernate as server to db connection.

Problem

I have one save button and for each click on button, envers creates one revision, whether there is no change in table values. Basically it is not checking old data to new data, just creating revisions.

Here is my bean code

@Entity
@Audited
@Table(name = "DOMAIN")
public class Domain implements java.io.Serializable {

private Long domainId;
private String domainName;
private String dataType;
private Long valueSize;
private Long valuePrecision;
private Long valueScale;
private String valueRangeLow;
private String valueRangeHigh;
private String description;
private String comments;
private Date effectiveStartDate;
private Date effectiveEndDate;
private String status;

public Domain() {
}

public Domain(Long domainId, String domainName, String dataType,
        Date effectiveStartDate, Date effectiveEndDate, String status) {
    this.domainId = domainId;
    this.domainName = domainName;
    this.dataType = dataType;
    this.effectiveStartDate = effectiveStartDate;
    this.effectiveEndDate = effectiveEndDate;
    this.status = status;
}

public Domain(Long domainId, String domainName, String dataType,
        Long valueSize, Long valuePrecision,
        Long valueScale, String valueRangeLow, String valueRangeHigh,
        String description, String comments, Date effectiveStartDate,
        Date effectiveEndDate, String status) {
    this.domainId = domainId;
    this.domainName = domainName;
    this.dataType = dataType;
    this.valueSize = valueSize;
    this.valuePrecision = valuePrecision;
    this.valueScale = valueScale;
    this.valueRangeLow = valueRangeLow;
    this.valueRangeHigh = valueRangeHigh;
    this.description = description;
    this.comments = comments;
    this.effectiveStartDate = effectiveStartDate;
    this.effectiveEndDate = effectiveEndDate;
    this.status = status;
}

@Id
@GeneratedValue(generator = "DOMAIN_SEQ")
@SequenceGenerator(name="DOMAIN_SEQ", sequenceName="DOMAIN_SEQ",allocationSize=1)
@Column(name = "DOMAIN_ID", unique = true, nullable = false, precision = 22, scale = 0)
public Long getDomainId() {
    return this.domainId;
}

public void setDomainId(Long domainId) {
    this.domainId = domainId;
}

@Column(name = "DOMAIN_NAME", nullable = false, length = 50)
public String getDomainName() {
    return this.domainName;
}

public void setDomainName(String domainName) {
    this.domainName = domainName;
}

@Column(name = "DATA_TYPE", nullable = false, length = 50)
public String getDataType() {
    return this.dataType;
}

public void setDataType(String dataType) {
    this.dataType = dataType;
}

@Column(name = "VALUE_SIZE", precision = 22, scale = 0)
public Long getValueSize() {
    return this.valueSize;
}

public void setValueSize(Long valueSize) {
    this.valueSize = valueSize;
}

@Column(name = "VALUE_PRECISION", precision = 22, scale = 0)
public Long getValuePrecision() {
    return this.valuePrecision;
}

public void setValuePrecision(Long valuePrecision) {
    this.valuePrecision = valuePrecision;
}

@Column(name = "VALUE_SCALE", precision = 22, scale = 0)
public Long getValueScale() {
    return this.valueScale;
}

public void setValueScale(Long valueScale) {
    this.valueScale = valueScale;
}

@Column(name = "VALUE_RANGE_LOW", length = 50)
public String getValueRangeLow() {
    return this.valueRangeLow;
}

public void setValueRangeLow(String valueRangeLow) {
    this.valueRangeLow = valueRangeLow;
}

@Column(name = "VALUE_RANGE_HIGH", length = 50)
public String getValueRangeHigh() {
    return this.valueRangeHigh;
}

public void setValueRangeHigh(String valueRangeHigh) {
    this.valueRangeHigh = valueRangeHigh;
}

@Column(name = "DESCRIPTION", length = 200)
public String getDescription() {
    return this.description;
}

public void setDescription(String description) {
    this.description = description;
}

@Column(name = "COMMENTS")
public String getComments() {
    return this.comments;
}

public void setComments(String comments) {
    this.comments = comments;
}

@Temporal(TemporalType.DATE)
@Column(name = "EFFECTIVE_START_DATE", nullable = false, length = 7)
public Date getEffectiveStartDate() {
    return this.effectiveStartDate;
}

public void setEffectiveStartDate(Date effectiveStartDate) {
    this.effectiveStartDate = effectiveStartDate;
}

@Temporal(TemporalType.DATE)
@Column(name = "EFFECTIVE_END_DATE", nullable = false, length = 7)
public Date getEffectiveEndDate() {
    return this.effectiveEndDate;
}

public void setEffectiveEndDate(Date effectiveEndDate) {
    this.effectiveEndDate = effectiveEndDate;
}

@Column(name = "STATUS", nullable = false, length = 50)
public String getStatus() {
    return this.status;
}

public void setStatus(String status) {
    this.status = status;
}

Problem is only with client server application.

With normal standalone program it is working fine.

Could anyone help me? I stuck at this point. Am i missing any jars or anything else? If you need more clarification about question then please tell me.

SERVER SIDE CODE

public long saveDomainFromJson(String domainJsonData) throws Exception {
    long domainId = 0;
    try {
        // here I am setting data to bean, getting from client side
        Domain domain = getDomainFromJson(domainJsonData);           

        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();

        domainId  = session.saveOrUpdate(domain);

        tx.commit();
        HibernateUtil.closeSession();

    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
    return domainId;
}

Json Data

{
  "DOMAIN_ID":36,
  "DOMAIN_NAME":"Test_Type",
  "DOMAIN_DATA_TYPE":"STRING",
  "DOMAIN_EFF_START_DATE":"2016-11-08",
  "DOMAIN_EFF_END_DATE":"2099-12-31",
  "DOMAIN_STATUS":"Draft",
  "DOMAIN_DESCRIPTION":"Object Type: Added for testing purpose"
}    

Solution

  • Sorry I didn't see this soon, but the problem is your call to session#save. From the javadocs for Session here, you'll notice the following passage:

    save() and persist() result in an SQL INSERT, delete() in an SQL DELETE and update() or merge() in an SQL UPDATE. Changes to persistent instances are detected at flush time and also result in an SQL UPDATE. saveOrUpdate() and replicate() result in either an INSERT or an UPDATE.

    So you basically want to use session#saveOrUpdate so that you get both insert and update semantics based on the state of your entity.

    Since session#save is generating a new INSERT operation, Envers will always create a new revision for that case regardless.