• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Liutauras Vilda
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Scott Selikoff
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
  • Frits Walraven
Bartenders:
  • Stephan van Hulst
  • Carey Brown

EJB 3 IN ACTION - EntityManager merge() and refresh() method conflict

 
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I am pretty new to EJBs.

The above sample code is from "EJB 3 in Action" book pages 303 and 304.

@Stateless
public class ItemManagerBean implements ItemManager {
@PersistenceContext(unitName="actionBazaar")
private EntityManager entityManager;
public ItemManagerBean() {}

public Item addItem(String title, String description, byte[] picture, double initialPrice, long sellerId) {
Item item = new Item();
item.setTitle(title);
item.setDescription(description);
item.setPicture(picture);
item.setInitialPrice(initialPrice);

Seller seller = entityManager.find(Seller.class, sellerId);

item.setSeller(seller);
entityManager.persist(item);

return item;
}

public Item updateItem(Item item) {
entityManager.merge(item);
return item;
}

public Item undoItemChanges(Item item) {
entityManager.refresh(entityManager.merge(item));
return item;
}

public void deleteItem(Item item) {
entityManager.remove(entityManager.merge(item));
}
}


Within the undoItemChanges() method the entityManager.merge() is called first on the item object before calling the entityManager.refresh() method.

I understnad that in this instance, the merge() is called before refresh() is to attach the item entity to the persistence context and also that any method invocation on EntityManager (like merge() or refresh()) will not get executed on the database straight away. I also understand that the merge() method is used to update the database from an object and the refresh() method is called to update and object from the databse.

According to the given code sample (ie. undoItemChanges() method), does the merge() method call will be over-written by the call to the refresh() method before they get executed on the database? That means the merge() method will not get executed on the database at all, which will stop updating the item record in the database.

Otherwise if the merge() get executed first and the refresh() get executed after on the database will the following scenario could happen? Let say the item object was already modified (different from the database record) while it was detached. When we execute merge() it will update the databse with the changes. When we call refresh() it will update the item object with latest data from the database. The state of the item object will be the same as before we executed undoItemChanges(). If this happens the undoItemChanges() method functionality will not be correct.

So, if I simplified my question, I am trying to figure out whether merge() and refresh() will be executed in that order on the database for the given code sample. If so, wouldn't that give an unexpected result.

Can someone please explain what will actually happen behind the scene?

Thanks in advance.
 
Greenhorn
Posts: 26
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think you make a confusion. To better understand, replace de database context for persistent context. The refresh and merge work only in persistent context independetly to database context. Other tip, merge don't update database, the only function for merge is to bring de entity object to persistent context.

I hope help.
 
Ranch Hand
Posts: 83
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Leonardo,

Other tip, merge don't update database, the only function for merge is to bring de entity object to persistent context.

.

you are partially right in this context. See the following extract from the book EJB3 in action.

EntityManager.merge updates the database with the data held in the entity,

 
Ranch Hand
Posts: 133
Eclipse IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

leonardo segala wrote:
Other tip, merge don't update database, the only function for merge is to bring de entity object to



Merge does update the database, refresh doesn't.
 
Ranch Hand
Posts: 62
Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tyronne Fernando wrote:
According to the given code sample (ie. undoItemChanges() method), does the merge() method call will be over-written by the call to the refresh() method before they get executed on the database? That means the merge() method will not get executed on the database at all, which will stop updating the item record in the database.

Otherwise if the merge() get executed first and the refresh() get executed after on the database will the following scenario could happen? Let say the item object was already modified (different from the database record) while it was detached. When we execute merge() it will update the databse with the changes. When we call refresh() it will update the item object with latest data from the database. The state of the item object will be the same as before we executed undoItemChanges(). If this happens the undoItemChanges() method functionality will not be correct.

Thanks in advance.



Even I have the same doubt, after going through the code in ejb3 in action.
merge() & refresh() will be executed in that order right? At first merge() gets executed which updates the database with the changed values; then refresh() gets executed which refreshes 'item' with the changed values. In that case this will cause the updates made on item; if any; when detached; to be updated in the database too, right? This is not the expected behavior from undoChanges() method right?
 
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi

The key for the "entityManager.refresh(entityManager.merge(item))" is the "flush". In this example everything is done in the same transaction (and no coresp. query are done), this is the reason why the merge only attach the given entity to the actual context after this the refresh get the database information and put it in the managed entity - the database contains the information committed with the last transaction.

Regards,
Mihai
 
Jisha Anand
Ranch Hand
Posts: 62
Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mihai Radulescu wrote:Hi

The key for the "entityManager.refresh(entityManager.merge(item))" is the "flush". In this example everything is done in the same transaction (and no coresp. query are done), this is the reason why the merge only attach the given entity to the actual context after this the refresh get the database information and put it in the managed entity - the database contains the information committed with the last transaction.

Regards,
Mihai



Mihai,

You mean to say that the merge operation here does not really do what it really is intended to do? In which all cases does the same happen? Is it like whenever more than one operation exists in single transaction, one overrides the other? Sorry for being so ignorant; I have just started preparing for scbcd.

Thanks in advance.
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Jisha

I don't want to say that "not really do what it really is intended to do", the behavior described in my previous post is according with the documentation - the flush(database sync.) is done when the transaction ends.
In the example you :
1. attach your entity to the persistence context (merge) so you have an entity in the persistence context cache but you don't flush the cache.
2.you overwrite the actual cache with the values from the database.

At least I hope that I am correct, what you guys think about ?

Regards,
Mihai
 
Jisha Anand
Ranch Hand
Posts: 62
Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mihai Radulescu wrote:
1. attach your entity to the persistence context (merge) so you have an entity in the persistence context cache but you don't flush the cache.



Mihai,

Thanks Mihai; I think I got the idea ; but few more doubts have risen.

So merge operation always attaches the entity to the persistence context? The function is to merge the changes in a managed entity to its corresponding database row. Of course the flush happens only when the transaction commits. In this case, it is like;
1. merge modifies the data in the cache.
2. but refresh operation takes the data from the database and updates the same cache & the result will be overwriting the data in the cache
3. when the transaction ends this data will be written to the database as part of the merge operation, but since this data was overwritten by refresh method the data ultimately written in the database will be the same as before. That is no change in data as such; but it will be rewritten to the DB?

Is my understanding correct?

In that case if it has a version field; it will be updated by the container; right?

Thanks again!
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Jisha

IMHO, when the transaction ends the actual persistence context gets synchronized with the database (it does not play a role how this changes occurs). In our case the entity get attached in the persistence context - with merge - and after this is altered. More, the alter process brings the entity in the same state with its corresponding database row so the sync process does not alter the database row, if the row is not altered then also the version remains the same.

Regards,
Mihai
 
Jisha Anand
Ranch Hand
Posts: 62
Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mihai Radulescu wrote:
so the sync process does not alter the database row, if the row is not altered then also the version remains the same.



Mihai,

You mean to say that the container checks for a data change; only if it has occurred the DB is updated; else not? Is that a mandatory feature for EJB container? I mean does the specification mandates the need to check for possible changes in the data before an update is made by any of the update operation; in our case, the operation being the merge?

Thanks!
Jisha
 
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

In the undoItemChanges method, our objective is to make the entity managed, and then load the data from the database into our entity instance. Why do we need to do a merge here? We can simply call the find() method, which willl solve our problem of making the entity managed, and then we can return the managed instance.

Even i was confused when i read the code from the book. It just does'nt seem appropriate because what is being done in the code seems to deviate from our purpose.

I personally think that using the find method is a much better option when performing the undo,the refresh and the remove operations because it keeps things in perspective.

I really dont know why the above code is correct. Why merge an entity when we are sure that we do not want to save its state in the database. Making it managed using the find method is far simpler and lucid.

Could anyone suggest a reason why we would want to prefer the merge method over the find method in such cases?

Regards
Ryan Sukale
 
Jisha Anand
Ranch Hand
Posts: 62
Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

ryan sukale wrote:In the undoItemChanges method, our objective is to make the entity managed, and then load the data from the database into our entity instance. Why do we need to do a merge here? We can simply call the find() method, which willl solve our problem of making the entity managed, and then we can return the managed instance.



Even I was thinking the same Ryan, using some other method to avoid the confusion. But if the merge operation does not touch the database then using merge or find is fine, right? But I am not sure whether merge updates only if data in the cache and that in the DB are not the same; I mean I am not sure whether the spec mandates that. If spec does not mandate it then there is a chance for version field, if used to get updated without actually changing the data, right?
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't

Ryan you are right, the merge is used only to make your resource managed. The find can have the same effect - the only problem can be performance, but this is other problem.

Jisha, I just do a small research - the merge generates an UPDATE and update increase the version even if the erst of the row remains the same. I will review the specification to be shore.

Regards,
Mihai
 
Jisha Anand
Ranch Hand
Posts: 62
Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mihai Radulescu wrote:
Jisha, I just do a small research - the merge generates an UPDATE and update increase the version even if the erst of the row remains the same. I will review the specification to be shore.



That is my understanding too Mihai. So in this case, usage of merge is unnecessary and we can say it is wrong from a design perspective because this will cause an actual DB update to rollback, right?
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No, I don't think that the database will roll back, the update will alter the needed rows even it the contains remain the same. The version will be increase also.
 
Jisha Anand
Ranch Hand
Posts: 62
Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mihai Radulescu wrote:No, I don't think that the database will roll back, the update will alter the needed rows even it the contains remain the same. The version will be increase also.



Mihai,

You got me wrong. What I am saying is that merge causes an unnecessary update & changes the version field value. Now when another transaction with genuinely changed data and version field value same as before the merge happened will get an OptimisticConcurrencyException, which is not programmatically wrong, but from a design perspective, is wrong. Please someone correct me if my understanding is wrong.

Thanks!
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Jisha

You are right the version increase without changes, this issue can be considered a small design flow. My only one plausible explanation is the performance, an extra check before merge will generate (at least) two operations a SELECT and an UPDATE so under some circumstances is good to sacrifice the design for performance.

regards,
Mihai
 
Jisha Anand
Ranch Hand
Posts: 62
Flex Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mihai Radulescu wrote:
under some circumstances is good to sacrifice the design for performance.



You are right Mihai! At some circumstances its good to sacrifice design or performance for the other; but in this case updating DB is a design flaw and doing a SELECT before merge might cause a performance flaw. So the best choice is to avoid merge and use find as Ryan pointed out, right?
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic