In MySQL it is possible to make a TIMESTAMP row being updated on every update operation. Is there a way to realize this for a column with Hibernate and map it to a POJO property?
So that I have something like this:
#Column
private Date updated;
If you want to do it at the database side, you can specify a custom column definition (if schema is generated by Hibernate, otherwise you need to declare it in your schema as desired), and instruct Hibernate that this property is generated at the database side:
#Column(columnDefinition = "TIMESTAMP ON UPDATE CURRENT TIMESTAMP")
#Generated(GenerationTime.ALWAYS)
private Date updated;
Alternatively, you can do it at the application side, as suggested by Jigar Joshi.
You can have this to accomplish this thing
#PreUpdate
protected void onUpdate() {
updated = new Date();
}
Related
I have an entity that has a field annotated with #CreationTimestamp:
#Entity
#Table(name = "foo")
class Foo {
...
#Column
#CreationTimestamp
private Instant createdAt;
}
And now I have integration tests where I need to create a few entries with different createdAt timestamps timestamp. But when I set the value to one that I need and save it's getting overridden with the creating timestamp of the VM:
Foo foo = new Foo();
foo.setCreatedAt(Instant.MIN);
foo = fooRepo.save(foo);
foo.getCreatedAt(); // equals to the creation time
How can I insert the desired values for this field in my test env?
I don't think it is possible to disable this behavior in an integration test as you need here.
However you can achieve the same using a workaround by setting the creation date after saving the entity, then save the entity once more to persist the new desired creation time.
This will work since #CreationTimestamp will only be triggered when saving the entity for the first time.
Instead of using #CreationTimestamp annotation, you could remove it from the field and manage that date with a #PrePersist:
#PrePersist
void onCreate() {
this.setCreatedAt(Instant.now());
}
Of course, you can check whatever you want in there. You could still have an updatable=false on the field.
I'm using Spring Boot with Spring Data JPA to map an Entity to a table in a SQL Server database for which I've created an #Embeddable composite key. There's a column I'd like to use as part of the key and according to SQuirreL its type name is datetime and the class name is java.sql.Timestamp. The key class looks like this:
#Embeddable
public class MyEntityIdentifier implements Serializable {
#Column(name = "LastUpdateDateTime")
private Timestamp lastUpdateDateTime;
...but the lastUpdateDateTime property always resolves to null without error. I've checked and there are no null fields for this column. I've also tried resolving to java.util.Date without success. Is there another type I should be using or something I'm doing wrong?
Hibernate will internally convert to a native Java type (i.e. java.util.Date as opposed to java.sql.Timestamp) by adding the #Temporal annotation.
#Column(name = "LastUpdateDateTime")
#Temporal(TemporalType.DATE)
private Date lastUpdateDateTime;
I am using EclipseLink 2.6.0 in my project together with MySQL 5.6.19.
Since mysql 5.6.4 supports a fieldtype DATETIME(6) which allows to store a date with milliseconds precision in its value. Also EclipseLink 2.6.0 says it supports this functionality.
I am creating a database from my entities. And I am not able to force it to create a proper field. In logs, during database creation I constantly see:
CREATE TABLE MY_TABLE (..., DATE_FIELD DATETIME ...)
when, obviously, what I want is:
CREATE TABLE MY_TABLE (..., DATE_FIELD DATETIME(6), ...)
I tried using both, simple and annotated version:
private java.util.Date date1;
#Temporal(value = TemporalType.TIMESTAMP)
private java.util.Date date2;
but the outcome is always the same. So how does the Eclipselink supports this? How to determine the proper field type?
Thanks specializt for the tip, easy solution:
#Column(length=6)
private Date myTime;
works also with YodaTime converter (description)
#Column(length=6)
#Converter(name = "dateTimeConverter", converterClass = pl.ds.eemediation.storage.entities.converters.JodaDateTimeConverter.class)
#Convert("dateTimeConverter")
private DateTime date;
When certain non key fields of a entity are generated in the database (for instance, by triggers) a call to persist will not bring back values that the database has just generated. In practice this means that you may need to refresh an entity after persist or merge (and when level 2 cache is enabled you may even need to evict the entity).
Hibernate have a custom annotation #Generated which handles Generated Properties.
// Refresh property 1 on insert and update
#Generated(GenerationTime.ALWAYS)
#Column(insertable = false, updatable = false)
private String property1;
// Refresh property 2 on insert
#Generated(GenerationTime.INSERT)
#Column(insertable = false)
private String property2;
JPA #GeneratedValue only works with primary key properties.
So, my question is if there is a replacement for #Generated on JPA API (maybe on 2.1)? And if there isn't one, what is the best practice to handle non key database generated fields?
I read the specs from the beginning until the end and it is not such thing, nothing comparable with #Generated, sorry , and as you said.
The GeneratedValue annotation may be applied to a primary key property
or field of an entity or mapped superclass in conjunction with the Id
annotation.
What you could do is use Event Listener #PrePersist and #PreUpdate to set some properties by default or generated by utility classes before em persist the object , try that approach it comes to my mind to something similiar.
I am using this code:
#Column(name = "FECHA_CREACION_TIMESTAMP",columnDefinition="DATE DEFAULT SYSDATE", insertable=false)
#Temporal(TemporalType.TIMESTAMP)
private Date fechaCreacionTimestamp;
But when I insert some data to the table, it doesn't have the date just have the date like null.
Updated Answer: (Now that I know that you are using Oracle)
What you need is to make sure that the column doesn't get included in the insert statements. For that, you need to update your #Column annoation like:
#Column(..other properties.., insertable = false)
See here for more details.
Now, you also need to make sure that the generated value is available in your domain object after you perform the insert. If you are using Hibernate, and do not mind using Hibernate annotations, you can put the following annotation on your field.
#org.hibernate.annotations.Generated(org.hibernate.annotations.GenerationTime.INSERT)
Hibernate will automatically perform the required select query for you.
If you are not using Hibernate, you will need to do a select yourself to fetch the generated value after performing the insert. JPA doesn't have anything to specify that this should be done automatically.
you can use something like :
#Column(name = "FECHA_CREACION_TIMESTAMP",columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP", insertable=false)
#Temporal(TemporalType.TIMESTAMP)
private Date fechaCreacionTimestamp;