Re: will nested sessions work? I.e. will a child session commit be auto-ignored?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: will nested sessions work? I.e. will a child session commit be auto-ignored?

Brian Barnett
So in a Struts world, I have an Action class that makes calls to
service classes. I currently have the transaction being started in the
service class, but this prevents me from being able to call other
service classes within my service classes. Would you suggest putting
the transaction logic, i.e., sqlSession creation, in the Action class,
or introduce a "transaction" layer of sorts between the Action and
Service classes? The latter seems like a waste, but just wanted to get
your take on this.

On Aug 17, 12:14 pm, Clinton Begin <[hidden email]> wrote:

> I agree with Nathan, but we need to redefine Unit of Work here to avoid
> confusion.  Usually Unit of Work is synonymous with Transaction... so to
> clarify what Nathan is saying, I'll just call it a "Statement".
>
> Working from the bottom up:
>
> * Statements is the smallest "piece of work" that may be part of a larger
> "unit of work"
> * Mappers contain many statements
> --- Mybatis ends here ----
> * DAOs use abstract and collect many mappers and statements
> * Service may call many DAOs
> * A Transaction or "Unit of Work" may include and scope around many calls to
> many services, daos, mappers and statements.
> * A Servlet/JSP request (or other UI event) may call many services
>
> What I've found (and it seems others like Nathan have as well) is that the
> DAO is the most useless piece of this already deep layering.
>
> So I (like Nathan) have generally reduced my stack to (now reversing the
> example above):
>
> Servlet / Controller / UI
>     -> Transaction Scope
>         -> Service
> --------------MyBatis Begins Here--------------
>            -> Mapper
>                 -> Statement
>
> No DAO layer.  MyBatis ensures that coding your statements and Mappers
> essentially boils down to writing a Java Interface and some SQL.  The
> Service is your business logic.  Transactions are transparent with a servlet
> filter (or similar interceptor approach), and hopefully a good Servlet
> framework (like Stripes) makes the controller layer almost non-existent from
> a coding perspective (in stripes it's literally just a method).
>
> Clinton
>
> On Mon, Aug 16, 2010 at 4:39 PM, Nathan Maves <[hidden email]>wrote:
>
> > I am going to give you my person/professional opinion so take it for
> > what it is worth.
>
> > DAO's are dead.  Part of the rewrite of MyBatis was to get rid of the
> > idea of a DAO and our old DAO framework.  A mapper is really your dao.
>
> > DAO's when used should be a single unit of work.  If you find yourself
> > calling one from the other you have done something wrong and rethink
> > it.  If it is hard to unit test rethink it :)
>
> > Use a service layer class when you need to combine multiple units of
> > work together.  Given your example I would create a AccountService
> > class that would use both the AccountMapper and the PlayerMapper.
> > Hand the transaction there.
>
> > DI is your friend.  USE IT
>
> > Nathan
>
> > On Sun, Aug 15, 2010 at 5:05 PM, Simon <[hidden email]> wrote:
> > > Dear Gurus,
>
> > > If one DAO calls another, are the transactions nested or treated as
> > > separate?
>
> > > e.g. below the PlayerDAO wants to use AccountDAO to create a new
> > > dependant object.  If AccountDAO succeeds, it calls commit.  Does this
> > > commit actuall happen on the DB at this point?  i.e. the code fails in
> > > PlayerDAO after the call of AccountDAO, will it roll back BOTH?  Or
> > > will I end up with a stranded account with no player in the example?
> > > Obviosly I could have a layer of business logic above the DAO which
> > > calls both DAOs, but this would have a worse issue as it would not
> > > have access to any transaction control.  Im using the defaut
> > > transaction manager (JDBC).  I havent worked out how to specify
> > > autocommit=false for everything, so i really hope the system is not
> > > autocommiting by default.
>
> > > public class AccountDAO{
> > >      public void create(Account account) {
> > >                SqlSession session =
> > > SqlSessionFactoryFactory.getFactory().openSession();
> > >                try {
> > >                        AccountMapper mapper =
> > session.getMapper(AccountMapper.class);
> > >                        mapper.insert(account);
> > >                        session.commit();
> > >                } finally {
> > >                        session.close();
> > >                }
> > >        assert (account.getId() > 0);
> > > }
>
> > > And now want to use it in DAO2:
>
> > > public class PlayerDAO{
> > >      public void create(Player player) {
> > >                SqlSession session =
> > > SqlSessionFactoryFactory.getFactory().openSession();
> > >                try {
> > >                        AccountDao accountDAO = new accountDAO();
> > >                        Account account = new Account();
> > >                        accountDAO.create(account);
>
> > >                        Player.setAccountId (account.getId());
> > >                        PlayerMapper mapper =
> > session.getMapper(PlayerMapper.class);
> > >                        mapper.insert(player);
> > >                        session.commit();
> > >                } finally {
> > >                        session.close();
> > >                }
> > >        assert (player.getId() > 0);
> > > }
>
> > > Or even worse, will the commit from the AccountDAO in the middle of
> > > the PlayerDAO commit any thing the PlayerDAO may have written and not
> > > committed yet (I presumt not, but cant find nested transaction info in
> > > the User guide).
>
> > > Is there a public area where knowlege and examples like this can be
> > > posted?  A public wiki perhaps?  If not, can I offer one?
Reply | Threaded
Open this post in threaded view
|

Re: will nested sessions work? I.e. will a child session commit be auto-ignored?

Clinton Begin
Administrator
I use a servlet filter to manage the lifecycle of the transaction.  An interceptor in your favourite web framework would work just as well.

Clinton

On Wed, Oct 6, 2010 at 1:06 PM, ooper <[hidden email]> wrote:
So in a Struts world, I have an Action class that makes calls to
service classes. I currently have the transaction being started in the
service class, but this prevents me from being able to call other
service classes within my service classes. Would you suggest putting
the transaction logic, i.e., sqlSession creation, in the Action class,
or introduce a "transaction" layer of sorts between the Action and
Service classes? The latter seems like a waste, but just wanted to get
your take on this.

On Aug 17, 12:14 pm, Clinton Begin <[hidden email]> wrote:
> I agree with Nathan, but we need to redefine Unit of Work here to avoid
> confusion.  Usually Unit of Work is synonymous with Transaction... so to
> clarify what Nathan is saying, I'll just call it a "Statement".
>
> Working from the bottom up:
>
> * Statements is the smallest "piece of work" that may be part of a larger
> "unit of work"
> * Mappers contain many statements
> --- Mybatis ends here ----
> * DAOs use abstract and collect many mappers and statements
> * Service may call many DAOs
> * A Transaction or "Unit of Work" may include and scope around many calls to
> many services, daos, mappers and statements.
> * A Servlet/JSP request (or other UI event) may call many services
>
> What I've found (and it seems others like Nathan have as well) is that the
> DAO is the most useless piece of this already deep layering.
>
> So I (like Nathan) have generally reduced my stack to (now reversing the
> example above):
>
> Servlet / Controller / UI
>     -> Transaction Scope
>         -> Service
> --------------MyBatis Begins Here--------------
>            -> Mapper
>                 -> Statement
>
> No DAO layer.  MyBatis ensures that coding your statements and Mappers
> essentially boils down to writing a Java Interface and some SQL.  The
> Service is your business logic.  Transactions are transparent with a servlet
> filter (or similar interceptor approach), and hopefully a good Servlet
> framework (like Stripes) makes the controller layer almost non-existent from
> a coding perspective (in stripes it's literally just a method).
>
> Clinton
>
> On Mon, Aug 16, 2010 at 4:39 PM, Nathan Maves <[hidden email]>wrote:
>
> > I am going to give you my person/professional opinion so take it for
> > what it is worth.
>
> > DAO's are dead.  Part of the rewrite of MyBatis was to get rid of the
> > idea of a DAO and our old DAO framework.  A mapper is really your dao.
>
> > DAO's when used should be a single unit of work.  If you find yourself
> > calling one from the other you have done something wrong and rethink
> > it.  If it is hard to unit test rethink it :)
>
> > Use a service layer class when you need to combine multiple units of
> > work together.  Given your example I would create a AccountService
> > class that would use both the AccountMapper and the PlayerMapper.
> > Hand the transaction there.
>
> > DI is your friend.  USE IT
>
> > Nathan
>
> > On Sun, Aug 15, 2010 at 5:05 PM, Simon <[hidden email]> wrote:
> > > Dear Gurus,
>
> > > If one DAO calls another, are the transactions nested or treated as
> > > separate?
>
> > > e.g. below the PlayerDAO wants to use AccountDAO to create a new
> > > dependant object.  If AccountDAO succeeds, it calls commit.  Does this
> > > commit actuall happen on the DB at this point?  i.e. the code fails in
> > > PlayerDAO after the call of AccountDAO, will it roll back BOTH?  Or
> > > will I end up with a stranded account with no player in the example?
> > > Obviosly I could have a layer of business logic above the DAO which
> > > calls both DAOs, but this would have a worse issue as it would not
> > > have access to any transaction control.  Im using the defaut
> > > transaction manager (JDBC).  I havent worked out how to specify
> > > autocommit=false for everything, so i really hope the system is not
> > > autocommiting by default.
>
> > > public class AccountDAO{
> > >      public void create(Account account) {
> > >                SqlSession session =
> > > SqlSessionFactoryFactory.getFactory().openSession();
> > >                try {
> > >                        AccountMapper mapper =
> > session.getMapper(AccountMapper.class);
> > >                        mapper.insert(account);
> > >                        session.commit();
> > >                } finally {
> > >                        session.close();
> > >                }
> > >        assert (account.getId() > 0);
> > > }
>
> > > And now want to use it in DAO2:
>
> > > public class PlayerDAO{
> > >      public void create(Player player) {
> > >                SqlSession session =
> > > SqlSessionFactoryFactory.getFactory().openSession();
> > >                try {
> > >                        AccountDao accountDAO = new accountDAO();
> > >                        Account account = new Account();
> > >                        accountDAO.create(account);
>
> > >                        Player.setAccountId (account.getId());
> > >                        PlayerMapper mapper =
> > session.getMapper(PlayerMapper.class);
> > >                        mapper.insert(player);
> > >                        session.commit();
> > >                } finally {
> > >                        session.close();
> > >                }
> > >        assert (player.getId() > 0);
> > > }
>
> > > Or even worse, will the commit from the AccountDAO in the middle of
> > > the PlayerDAO commit any thing the PlayerDAO may have written and not
> > > committed yet (I presumt not, but cant find nested transaction info in
> > > the User guide).
>
> > > Is there a public area where knowlege and examples like this can be
> > > posted?  A public wiki perhaps?  If not, can I offer one?