Reputation: 1256
I'm having problems where two Date fields are updated to the exact same date when only one should be. I'm trying to figure out why this is happening and how I can update only the one date field I want updated, and leave the other at its original value.
I'm using Hibernate with JPA on a MySQL database, in case that is part of the reason.
I have a persistence entity that looks something like this:
@NamedQueries({
@NamedQuery(name="MyObject.updateItem", query="UPDATE MyObject m SET m.item = :item, m.lastUpdate = :updated WHERE m.id = :id")
})
@Entity
@Table(name="entries")
public class MyObject implements Serializable
{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String item;
@Column(columnDefinition = "TIMESTAMP", nullable = false)
private Date dateCreated = new Date();
@Column(columnDefinition = "TIMESTAMP", nullable = false)
private Date lastUpdate = new Date();
// after here standard constructors, getters, setters, etc.
}
When from my DAO I call the NamedQuery
and provide the correct paramters, I find that both lastUpdate
and dateCreated
are changed. Is there any reason for this and how can I prevent this from happening? Is this caused because I initialize the to date fields in the entity class?
I'm using the TIMESTAMP
column definition because I want to be able to perform queries with <
or >
.
Upvotes: 1
Views: 344
Reputation: 1256
So I figured out the problem wasn't to do with my query or how I used persistence but how I built the database itself.
When I created the table to contain the data for the object I didn't specify a specific default for a NOT NULL
field.
My original SQL CREATE
statement looked something like this.
CREATE TABLE IF NOT EXISTS `entries` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`item` VARCHAR(255) NOT NULL,
`dateCreated` TIMESTAMP NOT NULL,
`lastUpdate` TIMESTAMP NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
When the MySQL Server executed this statement it deferred the first TIMESTAMP
field (in this case dateCreated
) with the default to fill it with the CURRENT_TIMESTAMP
and the attribute on update CURRENT_TIMESTAMP
which was unexpected by me.
I corrected this problem by changing default for the field to DEFAULT '0000-00-00 00:00:00'
and by changing my CREATE TABLE
statement to force this default so my new statement looks like
CREATE TABLE IF NOT EXISTS `entries` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`item` VARCHAR(255) NOT NULL,
`dateCreated` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastUpdate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
This apparently allows me to update the fields that I want without causing the other to update automatically.
I'm still not sure why MySQL assumed the defaults that it did. I guess it's probably somewhere in the documentation.
Upvotes: 0
Reputation: 287
I don't know if this will be a solution for you but this is what I commonly do for all of the entities I regularly implement. Add a PrePersist and PreUpdate function to your entity in order to set the created and last modified times. Also try adding @Temporal(TemporalType.TIMESTAMP) to each of your date fields.
@PrePersist
public void prePersist() {
this.dateCreated = new Date();
this.lastUpdated = this.dateCreated;
}
@PreUpdate
public void preUpdate() {
this.lastUpdated = new Date();
}
Beyond that, I'm a little stumped...
Upvotes: 0