Deferred Mapper Method Execution

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

Deferred Mapper Method Execution

Francesco Pellegrino
Dear All,
I am interested on achieving the possibility to defer the real statement execution from the statement preparation. I'll explain below what I mean:
  • the application prepares several classic Mappers:
            ie: MyMapper myMapper = session.getMapper(MyMapper.class);
            myMapper.doSomething(myId);
  • with the difference to don't execute the real statement during the doSomething method, but just prepare the statement with the related arguments
  • the application collects an array of prepared Mappers coming from different application areas
  • at the end the application executes the Mappers in the same transaction invoking the real mapperMethod.execute(sqlSession, args); (MapperProxy.java) having the possibility to commit or rollback all or nothing. Note that at this stage the application doesn't have the visibility of what was prepared inside the mappers. It just invokes a .execute method and store the resulting Object back to the result array.
Do you think this makes sense? If not, is there a way to implement this scenario in a different fashion?

Thank you
Francesco

--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Deferred Mapper Method Execution

unknown Mr.
Hi, I just saw this question, may I try?

Emmm, I don't know MyBatis inject the transaction at when.
I try to read the source code but it is complicated( So do not avoid it but mix in ).

Your goal is freeze sql and parameters as an entry, and you have a lot of entry like this, 
and you want to execute those entry at the right time,  I guess.

So, maybe you can find the way out at hibernate's criteria query, just freeze the sql and parameters.
And execute by interceptor when you want to do it.

The simpler way.

Just define you own interceptor, and return the token when catch your own signal
for example:

  Token token1 = aMapper.doSomething( boolean holdUp, ...args );
  Token token2 = bMapper.doSomething( boolean holdUp, ...args );

  Map<TokenId, Result> results = executorMapper.( List<Token> tokens );

This is class Token attribute:

  private MapperStatement statement;
  private Object[] unknownArgs;

The MapperStatement have all sql information what you need, whatever is strict sql or dynamic sql.

Of course, you can using ThreadLocal to transfer the signal if you think the method signature is not elegant enough.

And those job require modify MapperStatement at interceptor.
But I think you already know how implement it.

At the last, here is my MyBatis criteria query, for your reference: https://github.com/itfinally/mybatis-helper/tree/master/mybatis-jpa/src/main/java/top/itfinally/mybatis/jpa

Hope this can help you.

在 2018年10月13日星期六 UTC+8上午4:43:30,Francesco Pellegrino写道:
Dear All,
I am interested on achieving the possibility to defer the real statement execution from the statement preparation. I'll explain below what I mean:
  • the application prepares several classic Mappers:
            ie: MyMapper myMapper = session.getMapper(MyMapper.class);
            myMapper.doSomething(myId);
  • with the difference to don't execute the real statement during the doSomething method, but just prepare the statement with the related arguments
  • the application collects an array of prepared Mappers coming from different application areas
  • at the end the application executes the Mappers in the same transaction invoking the real mapperMethod.execute(sqlSession, args); (MapperProxy.java) having the possibility to commit or rollback all or nothing. Note that at this stage the application doesn't have the visibility of what was prepared inside the mappers. It just invokes a .execute method and store the resulting Object back to the result array.
Do you think this makes sense? If not, is there a way to implement this scenario in a different fashion?

Thank you
Francesco

--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Deferred Mapper Method Execution

unknown Mr.
In reply to this post by Francesco Pellegrino
Hi, I just saw this question, may I try?

Emmm, I don't know MyBatis inject the transaction at when.
I try to read the source code but it is complicated( So do not avoid it but mix in ).

Your goal is freeze sql and parameters as an entry, and you have a lot of entry like this, 
and you want to execute those entry at the right time,  I guess.

So, maybe you can find the way out at hibernate's criteria query, just freeze the sql and parameters.
And execute by interceptor when you want to do it.

The simpler way.

Just define you own interceptor, and return the token when catch your own signal
for example:

  Token token1 = aMapper.doSomething( boolean holdUp, ...args );
  Token token2 = bMapper.doSomething( boolean holdUp, ...args );

  Map<TokenId, Result> results = executorMapper.( List<Token> tokens );

This is class Token attribute:

  private MapperStatement statement;
  private Object[] unknownArgs;

The MapperStatement have all sql information what you need, whatever is strict sql or dynamic sql.

Of course, you can using ThreadLocal to transfer the signal if you think the method signature is not elegant enough.

And those job require remove the MapperStatement and replace with your target MapperStatement at interceptor.
But I think you already know how implement it.


Hope this can help you.

在 2018年10月13日星期六 UTC+8上午4:43:30,Francesco Pellegrino写道:
Dear All,
I am interested on achieving the possibility to defer the real statement execution from the statement preparation. I'll explain below what I mean:
  • the application prepares several classic Mappers:
            ie: MyMapper myMapper = session.getMapper(MyMapper.class);
            myMapper.doSomething(myId);
  • with the difference to don't execute the real statement during the doSomething method, but just prepare the statement with the related arguments
  • the application collects an array of prepared Mappers coming from different application areas
  • at the end the application executes the Mappers in the same transaction invoking the real mapperMethod.execute(sqlSession, args); (MapperProxy.java) having the possibility to commit or rollback all or nothing. Note that at this stage the application doesn't have the visibility of what was prepared inside the mappers. It just invokes a .execute method and store the resulting Object back to the result array.
Do you think this makes sense? If not, is there a way to implement this scenario in a different fashion?

Thank you
Francesco

--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Deferred Mapper Method Execution

Erwan Letessier
In reply to this post by Francesco Pellegrino
Not sure you need to go as deep as prepare and execute statement  (JDBC layer).
Command pattern should do the job.
The "prepared" mappers would the commands collected in the main application that will run a @Transactional method that iterate over commands to execute them.
Cheers.


On Fri, Oct 12, 2018, 22:43 Francesco Pellegrino <[hidden email]> wrote:
Dear All,
I am interested on achieving the possibility to defer the real statement execution from the statement preparation. I'll explain below what I mean:
  • the application prepares several classic Mappers:
            ie: MyMapper myMapper = session.getMapper(MyMapper.class);
            myMapper.doSomething(myId);
  • with the difference to don't execute the real statement during the doSomething method, but just prepare the statement with the related arguments
  • the application collects an array of prepared Mappers coming from different application areas
  • at the end the application executes the Mappers in the same transaction invoking the real mapperMethod.execute(sqlSession, args); (MapperProxy.java) having the possibility to commit or rollback all or nothing. Note that at this stage the application doesn't have the visibility of what was prepared inside the mappers. It just invokes a .execute method and store the resulting Object back to the result array.
Do you think this makes sense? If not, is there a way to implement this scenario in a different fashion?

Thank you
Francesco

--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Deferred Mapper Method Execution

Francesco Pellegrino
In reply to this post by unknown Mr.
Dear Mr,
Thank you for your answer!

Yes, you got my point and what I’m trying to achieve, I’m also trying to understand if there is a way out of the box to achieve it without changing batis core classes.

What about the project you attached, what is the purpose of that project? Is it similar to my case?

Thank you


> Il giorno sabato 13 ottobre 2018 12:21:37 UTC+3, unknown Mr. ha scritto:
> Hi, I just saw this question, may I try?
>
>
> Emmm, I don't know MyBatis inject the transaction at when.
> I try to read the source code but it is complicated( So do not avoid it but mix in ).
>
>
> Your goal is freeze sql and parameters as an entry, and you have a lot of entry like this, 
> and you want to execute those entry at the right time,  I guess.
>
>
> So, maybe you can find the way out at hibernate's criteria query, just freeze the sql and parameters.
> And execute by interceptor when you want to do it.
>
>
>
> The simpler way.
>
>
> Just define you own interceptor, and return the token when catch your own signal
> for example:
>
>
>   Token token1 = aMapper.doSomething( boolean holdUp, ...args );
>   Token token2 = bMapper.doSomething( boolean holdUp, ...args );
>
>
>   Map<TokenId, Result> results = executorMapper.( List<Token> tokens );
>
>
> This is class Token attribute:
>
>
>   private MapperStatement statement;
>   private Object[] unknownArgs;
>
>
> The MapperStatement have all sql information what you need, whatever is strict sql or dynamic sql.
>
>
> Of course, you can using ThreadLocal to transfer the signal if you think the method signature is not elegant enough.
>
>
> And those job require remove the MapperStatement and replace with your target MapperStatement at interceptor.
> But I think you already know how implement it.
>
>
> At the last, here is my MyBatis criteria query, for your reference: https://github.com/itfinally/mybatis-helper/tree/master/mybatis-jpa/src/main/java/top/itfinally/mybatis/jpa
>
>
> Hope this can help you.
> 在 2018年10月13日星期六 UTC+8上午4:43:30,Francesco Pellegrino写道:
>
> Dear All,
> I am interested on achieving the possibility to defer the real statement execution from the statement preparation. I'll explain below what I mean:
> the application prepares several classic Mappers:
>             ie: MyMapper myMapper = session.getMapper(MyMapper.class);
>             myMapper.doSomething(myId);
> with the difference to don't execute the real statement during the doSomething method, but just prepare the statement with the related arguments
> the application collects an array of prepared Mappers coming from different application areas
>
> at the end the application executes the Mappers in the same transaction invoking the real mapperMethod.execute(sqlSession, args); (MapperProxy.java) having the possibility to commit or rollback all or nothing. Note that at this stage the application doesn't have the visibility of what was prepared inside the mappers. It just invokes a .execute method and store the resulting Object back to the result array.
>
> Do you think this makes sense? If not, is there a way to implement this scenario in a different fashion?
>
>
> Thank you
> Francesco
--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Deferred Mapper Method Execution

unknown Mr.
Dear Pellegrino,

In my opinion, your goal have two solution, just like the previous reply.( Maybe have other better option, I haven't found it yet. )

1. Criteria query, just like Hibernate framework did, using Java code to write you sql. 
    It can store sql information and parameters in criteria object and waiting you executed.( This is also what my project does, don't use it, not finish yet. )

2. Store all MappedStatements by Interceptor, and execute when you send the signal.
    This is the easiest solution I think of, based on you question.

No matter which you choose, you need the Interceptor, because only Interceptor can replace the MapperStatement.

All you have to do is give the right MapperStatement to MyBatis and let it executed.

No batis core classes change.

And the project what I proposed have a file JpaPrepareInterceptor:
https://github.com/itfinally/mybatis-helper/blob/master/mybatis-jpa/src/main/java/top/itfinally/mybatis/jpa/JpaPrepareInterceptor.java

It can teach you how to replace the MapperStatement in the right way.

At the last, describe my design:

1. Write a class Token, It have three attribute, Id / Statement / Parameters.
2. Use ThreadLocal to store signal, and interceptor should be check it, just pass if no signal, 
    or get Statement, Parameter from interceptor and store into Token if signal is exists, and return this Token. ( That mean no query by this time if you return Token )
3. Use other Mapper to post query, and use all Token as parameters. when Interceptor get it, execute it, and return.( This is a real query )


在 2018年10月13日星期六 UTC+8下午6:55:42,Francesco Pellegrino写道:
Dear Mr,
Thank you for your answer!

Yes, you got my point and what I’m trying to achieve, I’m also trying to understand if there is a way out of the box to achieve it without changing batis core classes.

What about the project you attached, what is the purpose of that project? Is it similar to my case?

Thank you


> Il giorno sabato 13 ottobre 2018 12:21:37 UTC+3, unknown Mr. ha scritto:
> Hi, I just saw this question, may I try?
>
>
> Emmm, I don't know MyBatis inject the transaction at when.
> I try to read the source code but it is complicated( So do not avoid it but mix in ).
>
>
> Your goal is freeze sql and parameters as an entry, and you have a lot of entry like this, 
> and you want to execute those entry at the right time,  I guess.
>
>
> So, maybe you can find the way out at hibernate's criteria query, just freeze the sql and parameters.
> And execute by interceptor when you want to do it.
>
>
>
> The simpler way.
>
>
> Just define you own interceptor, and return the token when catch your own signal
> for example:
>
>
>   Token token1 = aMapper.doSomething( boolean holdUp, ...args );
>   Token token2 = bMapper.doSomething( boolean holdUp, ...args );
>
>
>   Map<TokenId, Result> results = executorMapper.( List<Token> tokens );
>
>
> This is class Token attribute:
>
>
>   private MapperStatement statement;
>   private Object[] unknownArgs;
>
>
> The MapperStatement have all sql information what you need, whatever is strict sql or dynamic sql.
>
>
> Of course, you can using ThreadLocal to transfer the signal if you think the method signature is not elegant enough.
>
>
> And those job require remove the MapperStatement and replace with your target MapperStatement at interceptor.
> But I think you already know how implement it.
>
>
> At the last, here is my MyBatis criteria query, for your reference: <a href="https://github.com/itfinally/mybatis-helper/tree/master/mybatis-jpa/src/main/java/top/itfinally/mybatis/jpa" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fitfinally%2Fmybatis-helper%2Ftree%2Fmaster%2Fmybatis-jpa%2Fsrc%2Fmain%2Fjava%2Ftop%2Fitfinally%2Fmybatis%2Fjpa\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHaC2TWuDxo-J78mSompRl73goIpw&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fitfinally%2Fmybatis-helper%2Ftree%2Fmaster%2Fmybatis-jpa%2Fsrc%2Fmain%2Fjava%2Ftop%2Fitfinally%2Fmybatis%2Fjpa\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHaC2TWuDxo-J78mSompRl73goIpw&#39;;return true;">https://github.com/itfinally/mybatis-helper/tree/master/mybatis-jpa/src/main/java/top/itfinally/mybatis/jpa
>
>
> Hope this can help you.
> 在 2018年10月13日星期六 UTC+8上午4:43:30,Francesco Pellegrino写道:
>
> Dear All,
> I am interested on achieving the possibility to defer the real statement execution from the statement preparation. I'll explain below what I mean:
> the application prepares several classic Mappers:
>             ie: MyMapper myMapper = session.getMapper(MyMapper.class);
>             myMapper.doSomething(myId);
> with the difference to don't execute the real statement during the doSomething method, but just prepare the statement with the related arguments
> the application collects an array of prepared Mappers coming from different application areas
>
> at the end the application executes the Mappers in the same transaction invoking the real mapperMethod.execute(sqlSession, args); (MapperProxy.java) having the possibility to commit or rollback all or nothing. Note that at this stage the application doesn't have the visibility of what was prepared inside the mappers. It just invokes a .execute method and store the resulting Object back to the result array.
>
> Do you think this makes sense? If not, is there a way to implement this scenario in a different fashion?
>
>
> Thank you
> Francesco

--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Deferred Mapper Method Execution

Francesco Pellegrino
Dear Mr,
thank you very much for your time.
I think I will go for the option 2 after checking your example.

Thank you!

Il giorno sabato 13 ottobre 2018 15:45:09 UTC+3, unknown Mr. ha scritto:

> Dear Pellegrino,
>
> In my opinion, your goal have two solution, just like the previous reply.( Maybe have other better option, I haven't found it yet. )
>
> 1. Criteria query, just like Hibernate framework did, using Java code to write you sql. 
>     It can store sql information and parameters in criteria object and waiting you executed.( This is also what my project does, don't use it, not finish yet. )
>
>
> 2. Store all MappedStatements by Interceptor, and execute when you send the signal.
>     This is the easiest solution I think of, based on you question.
>
>
> No matter which you choose, you need the Interceptor, because only Interceptor can replace the MapperStatement.
>
>
> All you have to do is give the right MapperStatement to MyBatis and let it executed.
>
>
> No batis core classes change.
>
> And the project what I proposed have a file JpaPrepareInterceptor:
> https://github.com/itfinally/mybatis-helper/blob/master/mybatis-jpa/src/main/java/top/itfinally/mybatis/jpa/JpaPrepareInterceptor.java
>
>
> It can teach you how to replace the MapperStatement in the right way.
>
>
>
> At the last, describe my design:
>
>
> 1. Write a class Token, It have three attribute, Id / Statement / Parameters.
> 2. Use ThreadLocal to store signal, and interceptor should be check it, just pass if no signal, 
>     or get Statement, Parameter from interceptor and store into Token if signal is exists, and return this Token. ( That mean no query by this time if you return Token )
> 3. Use other Mapper to post query, and use all Token as parameters. when Interceptor get it, execute it, and return.( This is a real query )
>
>
>
> 在 2018年10月13日星期六 UTC+8下午6:55:42,Francesco Pellegrino写道:Dear Mr,
>
> Thank you for your answer!
>
>
>
> Yes, you got my point and what I’m trying to achieve, I’m also trying to understand if there is a way out of the box to achieve it without changing batis core classes.
>
>
>
> What about the project you attached, what is the purpose of that project? Is it similar to my case?
>
>
>
> Thank you
>
>
>
>
>
> > Il giorno sabato 13 ottobre 2018 12:21:37 UTC+3, unknown Mr. ha scritto:
>
> > Hi, I just saw this question, may I try?
>
> >
>
> >
>
> > Emmm, I don't know MyBatis inject the transaction at when.
>
> > I try to read the source code but it is complicated( So do not avoid it but mix in ).
>
> >
>
> >
>
> > Your goal is freeze sql and parameters as an entry, and you have a lot of entry like this, 
>
> > and you want to execute those entry at the right time,  I guess.
>
> >
>
> >
>
> > So, maybe you can find the way out at hibernate's criteria query, just freeze the sql and parameters.
>
> > And execute by interceptor when you want to do it.
>
> >
>
> >
>
> >
>
> > The simpler way.
>
> >
>
> >
>
> > Just define you own interceptor, and return the token when catch your own signal
>
> > for example:
>
> >
>
> >
>
> >   Token token1 = aMapper.doSomething( boolean holdUp, ...args );
>
> >   Token token2 = bMapper.doSomething( boolean holdUp, ...args );
>
> >
>
> >
>
> >   Map<TokenId, Result> results = executorMapper.( List<Token> tokens );
>
> >
>
> >
>
> > This is class Token attribute:
>
> >
>
> >
>
> >   private MapperStatement statement;
>
> >   private Object[] unknownArgs;
>
> >
>
> >
>
> > The MapperStatement have all sql information what you need, whatever is strict sql or dynamic sql.
>
> >
>
> >
>
> > Of course, you can using ThreadLocal to transfer the signal if you think the method signature is not elegant enough.
>
> >
>
> >
>
> > And those job require remove the MapperStatement and replace with your target MapperStatement at interceptor.
>
> > But I think you already know how implement it.
>
> >
>
> >
>
> > At the last, here is my MyBatis criteria query, for your reference: https://github.com/itfinally/mybatis-helper/tree/master/mybatis-jpa/src/main/java/top/itfinally/mybatis/jpa
>
> >
>
> >
>
> > Hope this can help you.
>
> > 在 2018年10月13日星期六 UTC+8上午4:43:30,Francesco Pellegrino写道:
>
> >
>
> > Dear All,
>
> > I am interested on achieving the possibility to defer the real statement execution from the statement preparation. I'll explain below what I mean:
>
> > the application prepares several classic Mappers:
>
> >             ie: MyMapper myMapper = session.getMapper(MyMapper.class);
>
> >             myMapper.doSomething(myId);
>
> > with the difference to don't execute the real statement during the doSomething method, but just prepare the statement with the related arguments
>
> > the application collects an array of prepared Mappers coming from different application areas
>
> >
>
> > at the end the application executes the Mappers in the same transaction invoking the real mapperMethod.execute(sqlSession, args); (MapperProxy.java) having the possibility to commit or rollback all or nothing. Note that at this stage the application doesn't have the visibility of what was prepared inside the mappers. It just invokes a .execute method and store the resulting Object back to the result array.
>
> >
>
> > Do you think this makes sense? If not, is there a way to implement this scenario in a different fashion?
>
> >
>
> >
>
> > Thank you
>
> > Francesco
--
You received this message because you are subscribed to the Google Groups "mybatis-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.