Reputation: 1892
Using Spring 3.1/JPA 2 provided by Hibernate 4.1.0.
I have a base class for all of my Entities that provides basic audit capabilities (update timestamp, version number etc.) Because other applications access our database, these must be set via Trigger.
My mapping looks like:
public abstract class AbstractBaseModel implements Serializable {
@Version
@Generated(GenerationTime.ALWAYS)
@Column(name = "VERSION", insertable = false, updatable = false)
protected Long version;
@Generated(GenerationTime.ALWAYS)
@Column(name = "UPDATE_TIMESTAMP", insertable = false, updatable = false)
protected Date updateDate;
...
}
The org.hibernate.engine.internal.increment(...)
method is always called when committing the transaction - and results in a StaleObjectStateException
.
Oddly enough if I set GenerationTime.NEVER
on the version column, hibernate still increments the version, but persists properly. The problem is that even when the version in the database does not get updated (e.g. no change on the table) the version returned from a merge will be 1 higher than the database value which, obviously will cause issues on subsequent saves.
My expectation would be that GenerationTime.ALWAYS
would tell hibernate to never attempt to increment the version and rely on the database to do so, and then after insert/update to select the updated value.
Can anyone tell me where I have gone wrong in my understanding and implementation?
Upvotes: 1
Views: 5297
Reputation: 1340
You can do it using DB by specifying the following in SQL column definition and in entity mapping. The example below is for MySQL:
create table if not exists table_name (
...
modified timestamp default current_timestamp on update current_timestamp not null,
...
);
And in code:
@Version
@Column(name = "modified", columnDefinition = "timestamp default current_timestamp on update current_timestamp")
private Date modified;
Upvotes: 0
Reputation: 1286
I do not have an answer to your actual question, but I do have a solution for your problem. :)
In Hibernate, it is perfectly valid to do this:
@Version
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "UPDATE_TIMESTAMP"
private Date updateDate;
This will make your update date your version, too. This is both leaner and automatically updates it for every merge on the entity.
By the way: I suggest making the members private and adding get
ters and set
ters to the class.
Upvotes: 0