hard time setting autogenerated time with hibernate JPA annotations - java

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;

Related

can JPA datetime column be automatically set on saving?

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.

How to initialize entities fields representing their datetime of insertion into database using JPA?

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

Created by , Updated by column cannot be null spring jpa error

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

auto generate timestamp

I have to auto generate timestamp when I am creating a new record and auto generate modified timestamp when I update a record.
can anybody tell me how do I implement this. I am using openJPA.
thanks in advance.
You can use the following code:
#Column
#Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
#Column
#Temporal(TemporalType.TIMESTAMP)
private Date lastModificationDate;
// getters, setters
#PrePersist
void updateDates() {
if (creationDate == null) {
creationDate = new Date();
}
lastModificationDate = new Date();
}
The easiest is to use #Version annotation (documentation here)
Just add the following to your entities:
#Version
private java.sql.Timestamp myTimestamp;
/// normal getters & setters here
And it will do it automatically

Setting a JPA timestamp column to be generated by the database?

In my SQL Server 2000 database, I have a timestamp (in function not in data type) column of type DATETIME named lastTouched set to getdate() as its default value/binding.
I am using the Netbeans 6.5 generated JPA entity classes, and have this in my code
#Basic(optional = false)
#Column(name = "LastTouched")
#Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;
However when I try to put the object into the database I get,
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.generic.Stuff.lastTouched
I've tried setting the #Basic to (optional = true), but that throws an exception saying the database doesn't allow null values for the TIMESTAMP column, which it doesn't by design.
ERROR JDBCExceptionReporter - Cannot insert the value NULL into column 'LastTouched', table 'DatabaseName.dbo.Stuff'; column does not allow nulls. INSERT fails.
I previously got this to work in pure Hibernate, but I have since switched over to JPA and have no idea how to tell it that this column is supposed to be generated on the database side. Note that I am still using Hibernate as my JPA persistence layer.
I fixed the issue by changing the code to
#Basic(optional = false)
#Column(name = "LastTouched", insertable = false, updatable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;
So the timestamp column is ignored when generating SQL inserts. Not sure if this is the best way to go about this. Feedback is welcome.
I realize this is a bit late, but I've had success with annotating a timestamp column with
#Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
This should also work with CURRENT_DATE and CURRENT_TIME. I'm using JPA/Hibernate with Oracle, so YMMV.
#Column(nullable = false, updatable = false)
#CreationTimestamp
private Date created_at;
this worked for me.
more info
Add the #CreationTimestamp annotation:
#CreationTimestamp
#Column(name="timestamp", nullable = false, updatable = false, insertable = false)
private Timestamp timestamp;
If you are doing development in Java 8 and Hibernate 5 Or Spring Boot JPA then use following annotation directly
in your Entity class. Hibernate gets the current timestamp from the VM and will insert date and time in database.
public class YourEntity {
#Id
#GeneratedValue
private Long id;
private String name;
#CreationTimestamp
private LocalDateTime createdDateTime;
#UpdateTimestamp
private LocalDateTime updatedDateTime;
…
}
I do not think that every database has auto-update timestamps (e.g. Postgres). So I've decided to update this field manually everywhere in my code. This will work with every database:
thingy.setLastTouched(new Date());
HibernateUtil.save(thingy);
There are reasons to use triggers, but for most projects, this is not one of them. Triggers dig you even deeper into a specific database implementation.
MySQL 5.6.28 (Ubuntu 15.10, OpenJDK 64-Bit 1.8.0_66) seems to be very forgiving, not requiring anything beyond
#Column(name="LastTouched")
MySQL 5.7.9 (CentOS 6, OpenJDK 64-Bit 1.8.0_72) only works with
#Column(name="LastTouched", insertable=false, updatable=false)
not:
FAILED: removing #Temporal
FAILED: #Column(name="LastTouched", nullable=true)
FAILED: #Column(name="LastTouched", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
My other system info (identical in both environments)
hibernate-entitymanager 5.0.2
hibernate-validator 5.2.2
mysql-connector-java 5.1.38
I have this working well using JPA2.0 and MySQL 5.5.10, for cases where I only care about the last time the row was modified. MySQL will create a timestamp on first insertion, and every time UPDATE is called on the row. (NOTE: this will be problematic if I cared whether or not the UPDATE actually made a change).
The "timestamp" column in this example is like a "last-touched" column.x`
The code below uses a separate column "version" for optimistic locking.
private long version;
private Date timeStamp
#Version
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
// columnDefinition could simply be = "TIMESTAMP", as the other settings are the MySQL default
#Column(name="timeStamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
#Temporal(TemporalType.TIMESTAMP)
public Date getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(Date timeStamp) {
this.timeStamp = timeStamp;
}
(NOTE: #Version doesn't work on a MySQL "DATETIME" column, where the attribute type is "Date" in the Entity class. This was because Date was generating a value down to the millisecond, however MySQL was not storing the millisecond, so when it did a comparison between what was in the database, and the "attached" entity, it thought they had different version numbers)
From the MySQL manual regarding TIMESTAMP :
With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
If you mark your entity with #DynamicInsert e.g.
#Entity
#DynamicInsert
#Table(name = "TABLE_NAME")
public class ClassName implements Serializable {
Hibernate will generate SQL without null values. Then the database will insert its own default value. This does have performance implications See [Dynamic Insert][1].
This also works for me:-
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "CREATE_DATE_TIME", nullable = false, updatable = false, insertable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
public Date getCreateDateTime() {
return createDateTime;
}
public void setCreateDateTime(Date createDateTime) {
this.createDateTime = createDateTime;
}
I'm posting this for people searching for an answer when using MySQL and Java Spring Boot JPA, like #immanuelRocha says, only have too #CreationTimeStamp to the #Column in Spring, and in MySQL set the default value to "CURRENT_TIMESTAMP".
In Spring add just the line :
#Column(name = "insert_date")
#CreationTimestamp
private Timestamp insert_date;
#Column(name = "LastTouched", insertable = false, updatable = false, columnDefinition = "TIMESTAMP default getdate()")
#Temporal(TemporalType.TIMESTAMP)
private Date LastTouched;`enter code here`
This worked for me:
#Column(name = "transactionCreatedDate", nullable = false, updatable = false, insertable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")

Categories