Merge and get the to-be-updated version without flush?

Is it possible to change a versioned entity instance, and get the to-be-incremented-version without using flush ? Because from what i read, im afraid flush is not a good practice because it's bad impact for the performance or even data corruption ? Im not sure :D


Here's a simple code and also the output as the comment :

/*
    Hibernate: select receivingg0_.id as id9_14_, receivingg0_.creationDate as creation2_9_14_, ... too long
    the version before modification : 16
    the version after modification : 16
    after merge the modification, the version is : 16
    Hibernate: update ReceivingGood set creationDate=?, modificationDate=?, usercreate_id=?, usermodify_id=?,  ... too long
    after flushing the modification, the version is finally : 17
*/
public void modifyHeaderAndGetUpdatedVersion() {
    String id = "3b373f6a-9cd1-4c9c-9d46-240de37f6b0f";
    ReceivingGood receivingGood = em.find(ReceivingGood.class, id);
    System.out.println("the version before modification : " + receivingGood.getVersion());

    receivingGood.setTransactionNumber("NUM001xyz");
    System.out.println("the version after modification : " + receivingGood.getVersion());

    receivingGood = em.merge(receivingGood);
    System.out.println("after merge the modification, the version is : " + receivingGood.getVersion());

    em.flush();
    System.out.println("after flushing the modification, the version is finally : " + receivingGood.getVersion());
}

In my test, the version got incremented after the flush. The instance returned from the merge operation doesnt have the incremented version.

But in my case, i would like to return the entity to my webui in the form of DTO, and the entity should have the version-after-flush/commit before converting it to DTO and returning it to the UI to be rendered. And then the UI could have the latest version, and will pass this version for the next submission.


Is there any way where i can get the latest version without doing flush ?

Thank you !


UPDATE


In my experience, incrementing this manually can be problematic as can be seen from this example below. In this example, we have 2 flushes.

The 1st one is to synchronize the changes to the db connection, so that a stored procedure call from the same connection could see the changes made from the entityManager.

The second flush is called to get the final version. And we can see this is incremented twice. So getting version just from the manual increment without flushing wouldnt work in this condition, as we have to really count how many flushes are being made.

/*
Hibernate: select receivingg0_.id as id9_14_, receivingg0_.creationDate as creation2_9_14_, .. too long
the version before modification : 18
the version after modification : 18
after merge the modification, the version is : 18
now flushing the modification, so that the stored procedure call from the same connection can see the changes
Hibernate: update ReceivingGood set creationDate=?, modificationDate=?, usercreate_id=?, .. too long
after flushing the modification, the version is : 19
Hibernate: update ReceivingGood set creationDate=?, modificationDate=?, usercreate_id=?, .. too long
after the second flush, the version got increased again into : 20
*/
public void modifyHeaderAndGetUpdatedVersionWith2Flushes() {
    String id = "3b373f6a-9cd1-4c9c-9d46-240de37f6b0f";
    ReceivingGood receivingGood = em.find(ReceivingGood.class, id);
    System.out.println("the version before modification : " + receivingGood.getVersion());

    //auditEntity(receivingGood, getUser("3978fee3-9690-4377-84bd-9fb05928a6fc"));
    receivingGood.setTransactionNumber("NUM001xyz");
    System.out.println("the version after modification : " + receivingGood.getVersion());

    receivingGood = em.merge(receivingGood);
    System.out.println("after merge the modification, the version is : " + receivingGood.getVersion());
    System.out.println("now flushing the modification, so that the stored procedure call from the same connection can see the changes");
    em.flush();
    System.out.println("after flushing the modification, the version is : " + receivingGood.getVersion());

    receivingGood.setTransactionNumber("NUM001abc");

    em.flush();
    System.out.println("after the second flush, the version got increased again into : " + receivingGood.getVersion());
}

Does this mean i really have to depend on the flush at the end to get the latest version for the modified entity ?


UPDATE 2


Here's a simple example of a service method that will update the ReceivingGood entity and should return a DTO that has the newest version.

public ReceivingGoodDTO update(ReceivingGood entity) {
  // merge it
  entity = entityManager.merge(entity);

  // the version is not incremented yet, so do the flush to increment the version
  entityManager.flush(); // if i dont do this, the dto below will get the unincremented one

  // use a mapper, maybe like dozer, to copy the properties from the entity to the dto object, including the newest version of that entity
  ReceivingGoodDTO dto = mapper.map(entity, dto);

  return dto;
}

and here is an example that makes use of that method :

@Transactional
public ReceivingGoodDTO doSomethingInTheServiceAndReturnDTO() {
  // do xxx ..
  // do yyy ..
  dto = update(entity);
  return dto; // and the transaction commits here, but dto's version isnt increased because it's not a managed entity, just a plain POJO
}
7
задан bertie 11 March 2011 в 10:22
поделиться