Assume there is an entity like below:
#Entity
class MyEntity{
private Integer myValue;
private LocalDateTime time;
}
and the time is not exactly update time.
Sometime the record is handled like this:
myEntity.setMyValue(10);
myEntity.save();
and also this happens,
myEntity.setMyValue(11);
myEntity.setTime(LocalDateTime.now());
myEntity.save();
but I wonder if there is an alternative way to express the query like below
UPDATE my_entity SET time = now()
I know an annotation #LastModifiedDate but this time I can't use it..
You can use lifecycle events. You can add this method to your entity :
#PrePersist
#PreUpdate
public void saveTime() {
if(this.time == null) {
this.time = LocalDateTime.now();
}
}
You may place the #Column annotation over the time field in your entity and then specify a default value:
#Entity
class MyEntity {
private Integer myValue;
#Column(name="time", columnDefinition="DATETIME DEFAULT NOW()")
private LocalDateTime time;
}
Note that the above assumes that you are using MySQL which uses NOW() for the current datetime. This would have to change depending on your database, so this approach has some tight coupling between your application and the underlying database.
You could also define a default value directly on your database.
Related
My JPA Entity has one field like this:
#Column(nullable = false)
private LocalDateTime entryDateTime;
I want entryDateTime to be calculated when the entry is successfully inserted into database.
I think of two ways to do it:
Using #PostPersist method, in which case i need to remove #Column(nullable = false)
Using #PrePersist method, in which case #Column(nullable = false) can be there, but what if inserting somehow fails? I do not want my object to have entryDateTime initialized then, so i would need to set it back to null.
Designing entities might by affected by opinions, but i think the question is not opinion-based. I am looking for most efficient way, in which i would not need to remove #Column(nullable = false). Is there a way how to do it or a better approach? Or should i stick with one of those ways i described?
Which implementation of the jpa are you using?
In Hibernate you could annotate your Field with
#CreationTimestamp
Hibernate Doc
and in Spring you could annotate it with
#CreatedDate
Spring Doc
Create a method in your entity class annotated with PrePersist
for example:
public class UserEntity {
private Date createdAt;
...
#PrePersist
public void prePersist() {
createdAt = new Date();
}
}
That should work
I am using Hibernate core 5.4.22 and Hibernate common annotations 5.1.2. I have tried to save the update timestamp on the DB entry using the following annotation:
#UpdateTimestamp
private LocalDateTime closedDateTime;
Unfortunately, this works only when creating a new entry in the DB but not when updating the entry row.
According to the hibernate documentation:
The #UpdateTimestamp annotation instructs Hibernate to set the annotated entity attribute with the current timestamp value of the JVM when the entity is being persisted.
The supported property types are:
java.util.Date
java.util.Calendar
java.sql.Date
java.sql.Time
java.sql.Timestamp
You use direct update query, but the #UpdateTimestamp annotation does not work for this case.
Imagine you have the TestData entity:
#Entity
public class TestData
{
#Id
private Long id;
private String name;
#UpdateTimestamp
private LocalDateTime time;
}
So, you can create new entity in the following way:
TestData testData = new TestData();
testData.setId(1L);
testData.setName("Name 1");
entityManager.persist(testData);
or update existing entity in the following way:
TestData testData = entityManager.find(TestData.class, 1L);
testData.setName("Name 11");
testData = entityManager.merge(testData);
in the last case hibernate will update the time field automatically by the following query:
13:00:32,468 DEBUG SQL:144 - // update com.test.hibernate.entities.TestData
update TEST_SCHEMA.TST_TEST_DATA
set
name=?,
time=?
where
id=?
Context
My objective is to change the status of myObject if the day's date is equal to the date stored in myObject entity.
So, can you tell me and explain me what is the best way to execute a function every day at a specific time with H2 database and Java?
My entity
#Entity
public MyObject {
#Id
private String id;
private LocalDate endDate;
private boolean status; // true: on going , false: ended
...
}
My idea
Used the annotation #Schedule like this
#Scheduled(cron = "0 0 0 * * ?")
public void checkMyObjectsEnd() {
...
}
Conclusion
Or maybe H2 has native functions to do this? Like CREATE EVENT on SQL.
Thanks for your advice.
I'm trying to setup hibernate in my new project and I have this problem. I'm using oracle database.
In some tables I have more than one column that are timestamp.
Hibernate maps this columns as Serializable.
I tried to change manually to LocalTime type but the project won't even run. I change both on Availability.java and Availability.hbm.xml.
Is it supposed to be Serializable? I would like to use LocalTime instead. Is there a way to do this?
I found this: How to map oracle timestamp to appropriate java type in hibernate?. But it was 5 years ago and it seems like a complicated solution..
public class Availability implements java.io.Serializable {
private int id;
private Teacher teacher;
private byte month;
private short year;
private Serializable initialhour;
private Serializable endhour;
private String weekday;
public void setInitialhour(Serializable initialhour) {
this.initialhour = initialhour;
}
public Serializable getEndhour() {
return this.endhour;
}
}
You can just use:
private Timestamp initialhour;
If you want to can add annotation, but it should work just fine without it:
#Temporal(TemporalType.TIMESTAMP)
private Timestamp initialhour;
If you want to use java 8 DateTime you can use the #Type annotation, something like that:
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime initialhour;
Try to add hibernate-java8 to your project. The issue is that LocalTime is a Java8 class which Hibernate does not support by default.
The same happened to me, also with "interval to day" datatype, the easiest way I found to manually solve this was replacing "Serializable" for "Timestamp", not so clean but works for me.
thanks to you guys my knowlegde on hibernate has been improve dratiscally.
now i hit a block here about current_timestamp.
here is my codes
#Column(name="DATE_CREATED", insertable=false, updatable=false, columnDefinition="timestamp default current_timestamp")
#org.hibernate.annotations.Generated(value=GenerationTime.INSERT)
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date dateCreated;
#Column(name="LAST_MODIFIED", insertable=false, updatable=false, columnDefinition="datetime")
#org.hibernate.annotations.Generated(value=GenerationTime.ALWAYS)
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date lastModified;
i want date_created to get the current_timestamp and i want the lastmodified to insert the time for each updates.apparently i can't have 2 current_timestamp fields on the same table.Is there other ways to achieve that? thanks for reading
This is not related to Hibernate per se. Your annotations as specified above tell Hibernate that the values are going to be generated by the database and thus need to be reloaded after entity is inserted / updated.
If that's the way you want to go with, you need to configure your database (by creating a trigger, for example) to populate date_created / last_modified columns as needed.
Another approach is to not mark those fields as generated and instead update them in your java code. If you're using JPA (via Hibernate EntityManager), it's rather trivial to do this via #PrePersist / #PreUpdate callback method:
#PreUpdate
#PrePersist
public void updateTimeStamps() {
lastModified = new Date();
if (dateCreated==null) {
dateCreated = new Date();
}
}
You could achieve the same thing with hibernates #CreationTimestampand #UpdateTimestamp annotations e.g.
#Column(name = "CREATED")
#CreationTimestamp
private LocalDateTime created;
#Column(name = "LAST_UPDATED")
#UpdateTimestamp
private LocalDateTime lastUpdated;