And George, read this one:
http://stackoverflow.com/questions/10143880/hibernate-queries-much-slower-with-flushmode-auto-until-clear-is-called.
It explains why you experience the slow downs and what is it causing it.


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

> 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