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?

Turns out I was quite ignorant of some important concepts :) Now I
realize we were passing around an entity obtained from a different
EntityManager (A list of publishers), so of course making changes to
it in a whole new EntityManager (the editor's) doesn't make sense,
since that entity was part of the first EM's context. So I don't have
to call merge anymore since I'm now using find on my Editor's EM to
get the new entity I'll be changing for just that editor. Now things
are much less magical and are making sense :)

As for Unit of Work's expense, in a client app we're talking maybe at
max 15 entities being in any given context, so we'll see if that
becomes a resource problem, but it doesn't seem to be right now.

As for concurrency, we're not planning on re-using an entity manager
outside of a single scope, if we do we'll remember to keep track of
things.

The CRUD is shaping up,  now we're just playing with some JFace
Databinding. We'll post a link to the full example on the list here
(it uses the comic's derby db we borrowed from your demo). If we're
not doing anything too stupid we can plop it on the wiki and our
little blog, I'd hate to put some dangerous practices out there for
people right from the start :)

Thanks,
Tim

On Wed, Apr 2, 2008 at 1:42 PM, Shaun Smith <shaun.smith@xxxxxxxxxx> wrote:
>
>  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. ;-)
>
>      Shaun
>
>
>
>
>  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_DRIVER,
> "org.apache.derby.jdbc.ClientDriver");
>  properties.put(PersistenceUnitProperties.JDBC_URL,
> "jdbc:derby://localhost:1527/sample;create=true");
>  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();
>  transaction.begin();
>  }
>
>  public void close() {
>  transaction.rollback();
>  em.close();
>  }
>
>  public void updatePublisher(Publisher publisher) {
>  em.merge(publisher);
>  }
>
>  public void updateTitle(Title title) {
>  em.merge(title);
>  }
>
>  public void save() {
>  transaction.commit();
>  }
>
>  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
>
> _______________________________________________
>  eclipselink-users mailing list
>  eclipselink-users@xxxxxxxxxxx
>  https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>
>



-- 
./tch


Back to the top