You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
As Seam is a stateful framework, most use cases in Seam apps are modeled using conversational components. In order to use a conversation, you must extend the persistence context. Typically a Seam-managed persistence context (SMPC) is preferred over the EJB3 extended persistence context (read the Seam ref doc for reasons).
According to JPA with Hibernate book:
using an extended persistence context eliminates the detached object state. All instances are either transient (not known to a persistence context) or persistent (attached to a particular persistence context). This also eliminates the need for manual reattachment or merging of object state between contexts, which is one of the advantages of this strategy.
So here are the rules regarding the EntityManager interface's merge() method when needing to synchronize entity data with database table:
1) do use to merge an entity that is not already managed by the persistence context (e.g. entity is in transient state)
2) do not use to merge an entity that is already managed by the persistence context
Here is some reasons from Seam in Action as to why it's a bad idea to break rule 2:
Merging is a crude operation and should be avoided if possible. It first loads an entity instance with the same identifier as the detached instance into the current persistence context, resulting in a database read. Then, the property values from the detached instance are copied onto the properties of the managed instance. The main problem with this operation is that merging clobbers any changes that may have been made to the database record since the detached instance was retrieved (unless object versioning is used). There are other problems as well. If an entity instance with the same identifier as the detached instance has already been loaded into the current persistence context, a non-unique object exception is thrown because the uniqueness contract of entities in a persistence context is violated. You may also run into a lazy loading exception if you hit an uninitialized association on the detached instance during the merge. Avoid merging if at all possible. By using an extending persistence context, entity instances don’t become detached. Therefore, the persistence manager continues to track changes that are made to the entity. When it comes time to synchronize the entity with the database, calling the flush() method will do the trick within the scope of any transaction.
Example:
public void updateRepairCost() { EquipmentRepairCost erc = (EquipmentRepairCost)equipmentRepairCost[0]; erc.setCost(BigDecimal.valueOf(cost)); //don't need merge() if erc is in managed state //entityManager.merge(erc); entityManager.flush(); }
public void insertRepairCost() { EquipmentRepairCost erc = new EquipmentRepairCost(); erc.setCost(BigDecimal.valueOf(cost)); entityManager.persist(erc); entityManager.flush(); }
So what's an example of actually using the merge() method for a detached entity? This method comes in handy when you are not using an extended persistence context and the state of the entity actually can and does become detached.
Refer to Seam in Action, JP with Hibernate and Seam ref doc for more info.