Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] J2SE: Correct way to discard changes to a transaction?

Hi Tim,
We've been working on our SWT/RCP CRUD application and are running
into a strange anomaly. Example:
*Open Editor (this creates a new model & hence a new EntityManager)
*Change Field Value: this calls, merge on our EntityManager
*Editor is marked dirty, since em.getUnitOfWork().hasChanges() returns true.
*Close editor, do not save changes.
*Open up same record again in a new editor, my changes are still there
and em.getUnitOfWork().hasChanges() returns false.

When you rollback a transaction the state of the entities you read is not changed.  You should discard them and reread new managed instances that will reflect the correct state.

Some other things to watch out for include use of
		properties.put(PersistenceUnitProperties.CACHE_SHARED_DEFAULT, "false");
You want to use the shared cache by default.  I mistakenly included this in the examples I checked into SVN.

Another is that entityManager.merge(..) returns the object that the changes were merged into.  Keeping straight what is the managed vs. unmanaged instances can be tough.  Since you have a transaction open anyway why are you calling merge?  And how do you obtain references to the entities you're editing?

On reflection, I realize that UnitOfWork.hasChanges() can be expensive because it has to calculate changes--just like it has to do at commit time.  Byte code weaving (and change tracking) would make this cheaper but it isn't working at this point in OSGi.  Can you determine whether you need to commit some other way like editor field value changes? 

Also, you need to be careful with threads.  EntityManagers are not guaranteed thread safe.  In my RCP example I never got around to ensuring that concurrent threads spawned by the UI were not all executing queries in parallel--it was on my To Do list but the example did enough to make me happy so I've left it where it is. ;-)


Obviously there is some sort of caching going on, so what is the
correct way to discard changes to my transaction?
Backup Code:
Creating my EntityManagerFactory:
properties.put(PersistenceUnitProperties.TARGET_DATABASE, "Derby");
		properties.put(PersistenceUnitProperties.JDBC_USER, "app");
		properties.put(PersistenceUnitProperties.JDBC_PASSWORD, "app");
		properties.put(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MIN, "1");
		properties.put(PersistenceUnitProperties.JDBC_WRITE_CONNECTIONS_MIN, "1");
		properties.put(PersistenceUnitProperties.CACHE_SHARED_DEFAULT, "false");
		properties.put(PersistenceUnitProperties.BATCH_WRITING, "JDBC");
		properties.put("eclipselink.logging.level", "FINE");
		properties.put("eclipselink.logging.timestamp", "false");
		properties.put("eclipselink.logging.session", "false");
		properties.put("eclipselink.logging.thread", "false");
		emf = new PersistenceProvider().createEntityManagerFactory("comics",
properties, ComicsEntityManagerFactory.class.getClassLoader());

The "Model" that is created when an editor is opened:

public class PublisherEditorModel {
	private EntityManager em;
	private EntityTransaction transaction;
	public PublisherEditorModel() {
		em = ComicsEntityManagerFactory.createEntityManager();
		transaction = em.getTransaction();
	public void close() {
	public void updatePublisher(Publisher publisher) {
	public void updateTitle(Title title) {
	public void save() {

	public boolean isDirty() {
		UnitOfWork uow = ((EntityManagerImpl)em).getUnitOfWork();
		return uow.hasChanges();



Shaun Smith | Principal Product Manager, TopLink | +1.905.502.3094
Oracle Fusion Middleware
110 Matheson Boulevard West, Suite 100
Mississauga, Ontario, Canada L5R 3P4

Back to the top