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?

I'm glad to hear it's coming together!  Maybe when you're done you could contribute it and we can get it into the EclipseLink examples SVN repository?

     Shaun

Tim Hollosy wrote:
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


    


  

--


Oracle
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