Combine and get an updated version without a flash?

Is it possible to change instance instance with version and get version with be-be-incremented index without using flash? Because from what I read, I'm afraid that flash is not a good practice, because it affects performance badly or even data corruption? Im not sure: D


Here is a simple code, as well as the output as a 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 was increased after the flush. The instance returned from the merge operation does not have an incremental version.

But in my case, I would like to return the object to my webui in the form of DTO, and the entity must have a version after the / commit flush before converting it to DTO and returning it to the user interface. And then the user interface can have the latest version and will transmit this version for the next presentation.


Is there a way when I can get the latest version without a flash?

Thanks!


UPDATE


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

The first is the synchronization of changes to the db connection, so that a call to a stored procedure from the same connection can see the changes made to the entityManager.

The second flash is called to get the final version. And we see that it doubles . Thus, getting the version only from manual increment without flushing will not work in this state, since we must really count how many flushes are performed.

 /* 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 that I really have to depend on the flash at the end to get the latest version for the modified object?


UPDATE 2


Here is a simple example of a service method that will update a ReceivingGood object and should return a DTO that has the latest 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 uses this method:

 @Transactional public ReceivingGoodDTO doSomethingInTheServiceAndReturnDTO() { // do xxx .. // do yyy .. dto = update(entity); return dto; // and the transaction commits here, but dto version isnt increased because it not a managed entity, just a plain POJO } 
+7
source share
2 answers

Again, I recommend reading more about Hibernate and how it works, be it its documentation or Java Persistence with Hibernate.

You see this in a flash operation, because it happens where database updates happen. If you just lower the flash and complete the transaction, you will see the same behavior. Meaning, whenever your work unit ends, Hibernate cleans up the database changes. At this point, Hibernate compares and updates the version number. If the database version is 17 and you are updating version 16, Hibernate will throw an exception by updating the obsolete object.

However, you can “predict” what will be the next version by increasing 1 by the value that you have in your instance. But this will never be real, because it only effectively increases until the database record is updated. This way, any concurrent changes will not be displayed in your stream unless you query the database.

Edit:

You see two increments because you make two flushes. The "version" is a method of "optimistic" locking, that is, you expect only one thread to update a record during any unit of work (in a broader sense, think of as a "user action" where it lists the records, select one and update it ) The goal is to avoid Hibernate from updating an obsolete object, where two users select the same record for editing, make some parallel changes and update it. One of the corrections must be rejected, and the first wins the database. When you refresh a record twice (calling a flash twice), you see two increments. But this is really not about flash drives, but about "updates released in the database." If you had two transactions, you would see the same behavior.

However, it is worth noting that this method must be managed by Hibernate. You should not increase it yourself. It is often good practice not to provide setters for such fields.

In other words: you should consider the “version” as a read-only value and that you have no control over it. Thus, it is safe to display its value on the screen for the user, but it is unsafe to manage it (or "determine" the next version). At best, you can make the “best guess” by predicting that it will be current_version + 1.

+5
source

The latest version is the current one + 1. You can increase the version yourself in the entityToDto () method.

But in your example, executing a flash will not cause such a performance problem, IMO, since Hibernate will do this anyway during commit. There will be two flushes, but the second will no longer be anything for the flush.

0
source

All Articles