You might also want to use such kind of a utility that allows you to run in
transaction:

public interface InTransaction<T> {
      public T run(Session session);
}

public static <T> T DatabaseUtil.process(InTransaction<T>
transactionalRunnable) {
      try {
           Session session = currentSession(); //or newSession()
           if(!session.getTransaction().isActive())
                 session.beginTransaction();
           T result = transactionalRunnable.run(session);
           if(!session.getTransaction.isActive()) {
               session.getTransaction().commit();
               session.clear();
           }
      }
      catch(RuntimeException e) {
           if(session.getTransaction().isActive()) {
                session.getTransaction().rollback();
                session.clear(),
           }
      }
      finally {
           //session.close(); //if you created a new one
      }
}


This way you can control the whole transactional process while only doing:

List<Product> product = DatabaseUtil.process(new
InTransaction<List<Product>>() {
      List<Product> run(Session session) {
           //getUser etc are all static methods fetching from a ThreadLocal
RequestContext object so you dont need
           //to inject / pass along parts of your model in every
component/page
           UserInfo user = getUser();
           userStats.countUserRequest(user); //changes the database;
           return queryProductsForUser(user, session); //returning a list
      }
}

This example is just made up to demonstrate that you can return a
List<Product> or Integer or if you have nothing to return
a Void instance.

The DatabaseUtil class I use for everything that happends outside of a
request therefore when I have to control the sessions
being opened, closed and manage the transaction. This way you even not run
into any difficult with nesting (you can not
leave the transaction (since it is an enclosed try catch block),

I have set my session to automatically clear the persistence context on
commit.
You can do this by ((SessionImpl)session).setAutoClear(true).

And of cause checking if a transaction is active can be extracted to a
private method to value the DRY principle.




2013/10/25 Martin Kersten <martin.kersten...@gmail.com>

> >              session.flush();
> >              session.clear();
> >              hibernateSessionManager.commit();
>
> This is wrong.
> First on commit you will do the flush automatically (flush means all
> changes are written to the database (performing outstanding updates,
> inserts, deletes))
> Clear clears the persistence context of all entities not taking part on
> any outstanding flush event (as far as I remember) therefore Hibernate does
> a deep
> inspection of the active entities and removes all entities that were not
> encountered during that process.
> Commit commits the entities.
>
> So the correct usage is:
> session.getTransaction().commit();
> session.clear();
> session.beginTransaction();
>
> (without the clear its what HibernateSessionManager is doing with the
> session bound to the current thread).
>
>
>
>
> 2013/10/25 Martin Kersten <martin.kersten...@gmail.com>
>
>> Use:
>>
>> @Inject
>> Session session; //current session bound to the current thread
>>
>>
>> or
>>
>> @Inject
>> HibernateSessionSource source; + source.create() for a really new session
>> (CommitAfter would not work with newly created one);
>>
>> Using the Manager does give you only the session associated with the
>> current thread as would @Inject Session session; would do.
>>
>>
>>
>>
>> 2013/10/25 George Christman <gchrist...@cardaddy.com>
>>
>>> So I guess I'm still a little confused as to what is the best to do it.
>>> @CommitAfter seems to work fine for individual transactions but does not
>>> work well with batch jobs do to it holding on to the object in memory.
>>> Anyhow, I could not figure out how to get Martins
>>> session.getTransaction()
>>> to work, however I did end up getting the following code to work. Could
>>> someone tell me if I'm doing this correctly? Also should I be closing and
>>> rolling back the transaction?
>>>
>>>      //Mock scenario
>>>
>>>     @Inject
>>>     private HibernateSessionManager hibernateSessionManager;
>>>
>>>     public void onActionFromTest() {
>>>         Session session = hibernateSessionManager.getSession();
>>>
>>>         for (int i = 0; i < 100000; i++) {
>>>             employee = new Employee("George " + i);
>>>
>>>             session.save(employee);
>>>
>>>             if (i % 250 == 0) {
>>>                 session.flush();
>>>                 session.clear();
>>>                 hibernateSessionManager.commit();
>>>             }
>>>         }
>>>
>>>         session.flush();
>>>         session.clear();
>>>         hibernateSessionManager.commit();
>>>
>>>
>>>
>>> On Fri, Oct 25, 2013 at 9:07 AM, Thiago H. de Paula Figueiredo <
>>> thiag...@gmail.com> wrote:
>>>
>>> > On Fri, Oct 25, 2013 at 10:53 AM, Barry Books <trs...@gmail.com>
>>> wrote:
>>> >
>>> > While it's true you can run into problems by nesting @CommitAfter the
>>> same
>>> > > can be said about nesting any commits. The Tapestry database model is
>>> > > simple. There is one connection per request and when you call commit
>>> it
>>> > > does a commit.
>>> > >
>>> >
>>> > <pedantic>
>>> > Tapestry itself doesn't have any database model. It's a web framework
>>> and
>>> > nothing else. You can use it with any database, including none.
>>> > Tapestry-Hibernate is a package that provides *simple* support for
>>> > Hibernate and should be used in *simple* scenarios. If you need
>>> something
>>> > that's not simple, like any transaction handling not supported by
>>> > @CommitAfter, use Tapestry and some transaction handler (EJB,
>>> Spring-TX,
>>> > etc) but not Tapestry-Hibernate.
>>> > </pedantic>
>>> >
>>> >
>>> >
>>> > >
>>> > >
>>> > > On Fri, Oct 25, 2013 at 7:31 AM, Lance Java <
>>> lance.j...@googlemail.com
>>> > > >wrote:
>>> > >
>>> > > > I'm assuming a fork is broken too because it's no good for eating
>>> soup?
>>> > > > Sounds like you need a spoon, it's easy to write your own
>>> annotation...
>>> > > > Perhaps you want a @MaybeCommitAfter ;)
>>> > > >
>>> > >
>>> >
>>> >
>>> >
>>> > --
>>> > Thiago
>>> >
>>>
>>>
>>>
>>> --
>>> George Christman
>>> www.CarDaddy.com
>>> P.O. Box 735
>>> Johnstown, New York
>>>
>>
>>
>

Reply via email to