Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data JPA JpaRepository.save() does not return default values

I have a very confusing problem stealing a lot of time:

@Column(name = "created", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP", insertable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date created;

This code the timestamp is set in my Postgres DB but the repository returns a entity with created = null;

I've tried some annotations like:

@Generated

from : Spring Data JPA JpaRepository.save(entity) not returning database default values

But nothing worked for me.

like image 227
Daniel R. Avatar asked May 19 '15 13:05

Daniel R.


People also ask

What does the Save method return in Spring data JPA?

The save() method returns the saved entity, including the updated id field.

What is the difference between save and Saveflush in JPA?

Both methods are used to save entities to the database. Flushing is the process of synchronizing the state of the persistence context with the underlying database. When using saveAndFlush method, data immediately flush to the database and to do it with the save method we need to call flush() method explicitly.

What is difference between save and saveAll in JPA?

In our case, each time we call the save() method, a new transaction is created, whereas when we call saveAll(), only one transaction is created, and it's reused later by save().


2 Answers

The generated values are only guaranteed to be generated at flush time. Saving an entity only makes it "attached" to the persistence context. So, either you have to flush the entity manager explicitely.

Try to use entity.saveAndFlush() and it should work.

like image 51
trollr Avatar answered Oct 20 '22 10:10

trollr


Using Spring Data we were facing the same issue with sql server

We solved it using

import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;

@Generated(GenerationTime.INSERT)
@Column(name = "created", insertable = false, updatable = false)
private LocalDateTime created;

You can combine it saveAndFlush (From JpaRepository)

If nothing works you can either implement refresh method by extending SimpleJpaRepository or avoid using the database default and replace it with an EntityListener

@EnableJpaAuditing
public class ConfigClass {...}


@EntityListeners(AuditingEntityListener.class)
public class YourEntity {

    @Column(name = "created", insertable = false, updatable = false)
    @CreatedDate
    private LocalDateTime created;
}

Take in consideration that using EntityListener you have to remove the database default. You could set insertable=true and use ColumnTransformer

    @Column(name = "created", updatable = false)
    @ColumnTransformer(write = "coalesce(sysutcdatetime(), ?)")
    @CreatedDate
    private LocalDateTime created;
like image 42
Henry Avatar answered Oct 20 '22 09:10

Henry