4

I am adding spring JPA/Hibernate 5 to an old project. I am running CrudRepository .save(Entity) method against a Mainframe/DB2 table. The row is inserted just fine, but returnedEntity.getIdColumn() has 0 in it. I really need the ID for further processing. Could somebody please help? Thank you very much!

@Entity
Table(name="MY_TABLE")
public class myClass {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID_COLUMN")
private Long idColumn;
...

}

Identity is the only strategy type that worked. Here is the Service class:

@Transactional
public Entiry insertEntity(Entity originalEntity) {
   return MyRepository.save(originalEntity);
}
Runner class:
Entity originalEntity = createEntity();
Entity returnedEntity = ServiceClass.insertEntity(originalEntity);
System.out.println(originalEntity.getIdColumn());
System.out.println(returnedEntity.getIdColumn());
Elena
  • 61
  • 1
  • 4

3 Answers3

3

My guess is that you're trying to get an ID before your transaction was flushed to DB. Thus JPA doesn't know what id will be assigned and returns 0.

Edited: I'd recommend to have something like this:

@Transactional
public Entity save( .....) {
   //some code
   repository.save(entity);
   //some code
   return entity;
}

Transaction will be flushed at the end of this method and entity which will be returned from it should have a real id.

Andrew Preizner
  • 254
  • 1
  • 5
  • Thank you, Andrew. saveAndFlush() of JpaRepository did not help. Is there another way? – Elena Sep 29 '18 at 02:24
  • you're welcome) Is the method where you call save transactional? – Andrew Preizner Sep 29 '18 at 02:46
  • If it's transactional - data from hibernate session may not be flushed to DB till the end of this method. – Andrew Preizner Sep 29 '18 at 02:54
  • OK, I removed @Transactional and still having no luck. Do I have any options how to get the Id, or my efforts are doomed? :( Thank you – Elena Sep 29 '18 at 03:04
  • So, I tried exactly how you have it, but still got 0. Your version sounds like I would return the original Entity in hope JPA will update it. All other posts suggest that JPA returns a new, updated object. So, I added my version of the code above with interrogating the original Entity object as well as the returned one. Both return 0 – Elena Sep 29 '18 at 15:12
  • hm...interesting. What about Runner class, is the method which call insertEntity also Transactional? If yes, please add propagation level REQUIRES_NEW for the insertEntity method: @Transactional(propagation=Propagation.REQUIRES_NEW) – Andrew Preizner Sep 29 '18 at 17:09
  • For some reason it is complaining about propagation saying Cannot resolve method 'propagation'. Thank you – Elena Sep 30 '18 at 02:19
  • hm.. Do you mean inside the annotation or what do you mean by method 'propagation' ? – Andrew Preizner Oct 01 '18 at 22:40
  • Turns out I was using the wrong Transactinal. I switched to javax.persistance... and the error went away. The 0 returned value issue remains. From spring debug messages it looks like the transaction is commited before I Sysout it. So, I do not think it is my issue. For some reason DB2 does not return the true value. Somebody suggested using @Query, but it does not look it supports Insert. I am really stuck. :( – Elena Oct 02 '18 at 13:44
2

Turned out my table had an id sequence generator already defined in the DB. So, after I changed it to generationType.SEQUENCE it worked nicely. @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_TABLE_SEQ")

Elena
  • 61
  • 1
  • 4
1

Recently, I've faced with similar issue.

In my case, the new entity has been passed from UI and ID was 0 instead of NULL (since the type of ID was primitive on Java side). Therefore Hibernate didn't use right save strategy.

Eventually, I changed the type from long to Long and it helped:
private long id;
private Long id;

Also update method was changed from:

@PutMapping("/{id}")
public T update(@PathVariable ID id, @Valid @RequestBody T entity) {
    this.getService().update(entity);
    return entity;
}

to:

@PutMapping("/{id}")
public T update(@PathVariable ID id, @Valid @RequestBody T entity) {
    return this.getService().update(entity);
}

P.S.: When entity ID was 0, Hibernate was using merge strategy, however, it should persist strategy for new Entities instead (link for implementation of save method).

Leonid Dashko
  • 3,657
  • 1
  • 18
  • 26