Thanks Martin, if I understood you correctly, you are still Injecting the
Session. Will this cause any issues where I'm still using @CommitAfter?
Also in the batch job, do you typically put an additional commit outside
the loop to pickup up  the remaining values when they don't reach the
count, say % 250 == 0 mark or do you just put an additional condition in
there to commit when you hit the last record?

so something like this,

if(count % 250 == 0 || count == size)


On Fri, Oct 25, 2013 at 10:03 AM, Martin Kersten <
martin.kersten...@gmail.com> wrote:

> well you are decorating the session not the session source of cause... .
>
>
> 2013/10/25 Martin Kersten <martin.kersten...@gmail.com>
>
> > >> Perhaps you want a @MaybeCommitAfter ;)
> >
> > What about simply having @WriteTransaction (und @ReadTransaction, since
> > lacking support for read transactions is the biggest performance issue
> when
> > dealing with databases). If you are inside a method annotated with
> > @WriteTransaction it is ignored. If nesting write within a read
> transaction
> > fails (there is something wrong with your service methods / thinking).
> And
> > also wrapping the session source (decorate) and checking on any
> > save+/update/delete  + query if a transaction was set makes it crystal
> > clear if you messed up the transactional thingy. Also using @CommitAfter
> > inside a @XxxxTransaction fails, since you can not commit inside it
> without
> > breaking the meaning.
> >
> > This would make it possible to have a good implementation which is self
> > explaining, would only cost two hours to build and test (at least I
> havent
> > spent an hour in total I think). And it wont break the backward
> > compatibility with @CommitAfter.
> >
> >
> > 2013/10/25 Martin Kersten <martin.kersten...@gmail.com>
> >
> >> 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
> >>>>>>
> >>>>>
> >>>>>
> >>>>
> >>>
> >>
> >
>



-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Reply via email to