Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a fairly simple problem. In a single transaction, my code looks something like this:

MyClass c = new MyClass();
c.setPropA("A");

c = myClassRepository.save(c);

c.setPropC("C");

Where my entity looks like this:

@Entity
@Table(name = "MY_CLASS")
public class MyClass {
  private String propA;
  private String propB;
  private String propC;

  @Id
  @Column(name = "PROP_A", unique = true, nullable = false, updatable = false)
  public String getPropA() { return propA; }
  public void   setPropA(String propA) { this.propA = propA; }

  @Column(name = "PROP_B", insertable = false)
  public String getPropB() { return propB; }
  public void   setPropB(String propB) { this.propB = propB; }

  @Column(name = "PROP_C")
  public String getPropC() { return propC; }
  public void   setPropC(String propC) { this.propC = propC; }
}

And the database is set up like this (Dialect = Oracle 11G)

CREATE TABLE MY_CLASS {
  PROP_A VARCHAR2 NOT NULL PRIMARY KEY,
  PROP_B VARCHAR2 DEFAULT 'B' NOT NULL,
  PROP_C VARCHAR2
}

So, based on the code to persist the entity, I would think I'd get queries that look something like this:

MyClass c = new MyClass();
c.setPropA("A");

c = myClassRepository.saveAndFlush(c);
// INSERT INTO MY_CLASS (PROP_A, PROP_C) VALUES ("A", NULL)
// SELECT PROP_A, PROP_B, PROP_C FROM MY_CLASS -- to refresh `c`

c.setPropC("C");

// After transaction ends, flush change to `c.propC`
// UPDATE MY_CLASS SET PROP_B = "B", PROP_C = "C" WHERE PROP_A = "A"

... but the SELECT never happens. Why is the entity not refreshed?

This breaks because of the UPDATE that (immediately) follows the INSERT and c.propB is still null. I get a ORA-01407: cannot update ("MY_SCHEMA"."MY_CLASS"."PROP_B") to NULL stack trace.

I realize there are ways around this using @PrePersist or setting default values on columnDefinition in Java, but I shouldn't have to duplicate defaults.

Note: This worked before when I was using org.hibernate.Session.saveOrUpdate() instead of Spring Data JPA for this action.

Thanks in advance for any help!

like image 753
Andy Avatar asked Oct 28 '14 20:10

Andy


People also ask

What does JPA save return?

JPA's persist method returns void and Hibernate's save method returns the primary key of the entity.

Which is better CrudRepository or JpaRepository?

Crud Repository doesn't provide methods for implementing pagination and sorting. JpaRepository ties your repositories to the JPA persistence technology so it should be avoided. We should use CrudRepository or PagingAndSortingRepository depending on whether you need sorting and paging or not.


1 Answers

Hibernate doesn't know that B is generated by the database, and that it has to read it after insert, unless you tell it to do so using the @Generated annotation.

like image 192
JB Nizet Avatar answered Oct 04 '22 01:10

JB Nizet