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=?
Related
I have a collection in mongo containing both new data with the version field and old data imported from an old couchbase bucket which doesn't contain the version field.
How can I update an existing record? i.e. adding the version=0 automatically on save?
public class Entity {
private String someField;
#CreatedDate
private Instant createdAt;
#LastModifiedDate
private Instant updatedAt;
#Version
private Long version;
}
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.
I'm using spring boot JPA for CRUD operations. I'm querying the database table with the field name created_at which is of type date.There are some rows in the table with the given date but JPA is giving zero result set. I'm using Oracle 11g
Here is my entity
import java.sql.Date;
#Entity
#Table(name="veev_json")
public class VeevJson {
#Id
#Column(name="ID")
private int id;
#Column(name="CREATED_AT")
private Date createdDate;
}
My JPA Repository
import java.util.Date;
#Repository
public interface VeevJsonRepository extends JpaRepository<VeevJson, Integer> {
public List<VeevJson> findByCreatedDate(Date date);
}
Calling the function in the service layer
Date date = new Date(); //taking current date of type java.util.Date
List<VeevJson> documents = veevJsonRepository.findByCreatedDate(date);
My DB table structure
ID NUMBER(10,0)
CREATED_AT DATE
SQL query generated by the hibernate:
select veevjson0_.ID as ID1_1_, veevjson0_.CREATED_AT as CREATED_AT2_1_, veevjson0_.JSON as JSON3_1_, veevjson0_.STATUS as STATUS4_1_ from veev_json veevjson0_ where veevjson0_.CREATED_AT=?
When using a field with type Date, you should also use the #Temporal annotation. The default value of #Temporal is TemporalType.TIMESTAMP, and your JPA implementation may get confused about dealing with a field of type java.util.Date, passing as argument of query the timestamp instead of date.
Please annotate your field as
import java.util.Date;
#Entity
#Table(name = "veev_json")
public class VeevJson {
#Id
#Column(name = "ID")
private int id;
#Temporal(TemporalType.DATE)
#Column(name = "CREATED_AT")
public Date createdDate;
...
}
Doing so will allow JPA implementation to send as queried value only the date (probably in 'YYYY-MM-dd' format) instead of timestamp or any other value.
If you prefer and your JDBC supports 4.1 version, you may exchange the java.util.Date for java8 time API types, but I guess this is out of scope here.
I am using spring boot and jpa and i want to save data in table.
I have database table constraint not null on createdBy, updatedBy, updationDate, creatingDate columns.
I have similar DTO to entity and above mentioned audit fields are not in DTO but only in entity so meaning user don't send audit information.
On entity i am using this #EntityListeners(AuditingEntityListener.class).
Problem is when i try to update entity by rep.save(entity) i get this error "Column 'CreatedBy' cannot be null
My entity is using auditing entity listeners and it looks similar to this
#Column(name = "isactive")
private boolean active;
#CreatedBy
#Column(name = "createdby")
private String createdBy;
#CreatedDate
#Column(name = "creationdate")
private Instant creationDate;
#LastModifiedBy
#Column(name = "lastupdateby")
private String lastUpdateBy;
#LastModifiedDate
#Column(name = "lastupdatedate")
private Instant lastUpdateDate;
Note: If i try to create new object, it gets saved and worked fine and also audit information in database like created by updated by is also populated using auditing entity listener.
But when it try to update the same object i get the error of createdBy cannot be null, i am assuming these audit fields createdBy updatedBy .... should also be populated of filled by auditEntityListener the same way i create it by post request.
you can use the updatable = false flag, e.g.
#Column(name = "createdby", updatable = false)
and
#Column(name = "creationdate", updatable = false)
that helped me to solve this issue.
I got the solution, When we need to update the entity that is using AuditEntityListener
i updated only the changed fields in entity comparing to DTO.
MapStruct made it easy
void updateEntity(#MappingTarget Entity target, DTO dto);
now save the updated entity.
Have a look how to use Audit Aware in link
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;