ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Eduardo Macarron <eduardo.macar...@gmail.com>
Subject Re: MapperMethod caching?
Date Fri, 01 Jan 2010 16:17:17 GMT
Yes Clinton, is just for performance.


2010/1/1 Clinton Begin <clinton.begin@gmail.com>

> What problem are you trying to solve, or goal you're trying to achieve by
> doing this?  Is it strictly a performance consideration?
>
> Clinton
>
>
>
> On Fri, Jan 1, 2010 at 7:31 AM, Eduardo Macarron <
> eduardo.macarron@gmail.com> wrote:
>
>> Fist of all happy new year!
>>
>> Some work has been doing on Spring 3 and Ibatis 3 integration.
>>
>> Having a look at mappers internals we saw that a new MapperMethod is
>> created (with some introspection work) on each call to a mapper method. I
>> wonder if it would be better to build them all during startup or maybe cache
>> them somehow.
>>
>> this is the Jira issue (http://jira.springframework.org/browse/SPR-5991)
>> Grabriel Axel posted it here some months ago (he opened the issue)
>>
>> The main problem with this task is that MapperMethods are not thread safe
>> and that they hold an SqlSession. Enabling cache would require to make some
>> changes to MapperMethods. SqlSession should be passed as an argument to
>> execute instead to its constructor.
>>
>>  public MapperMethod(Method method, Configuration configuration) {
>>     paramNames = new ArrayList<String>();
>>     paramPositions = new ArrayList<Integer>();
>>     ...
>>
>>   public Object execute(Object[] args, SqlSession sqlSession) {
>>     Object result;
>>     if (SqlCommandType.INSERT == type) {
>>     ...
>>
>> And MapperProxy
>>
>>   public Object invoke(Object proxy, Method method, Object[] args) throws
>> Throwable {
>>     return new MapperMethod(method,
>> sqlSession.getConfiguration()).execute(args, sqlSession);
>>   }
>>
>>
>> So for example Spring could have this code to use directly injected
>> Mappers where SqlSession is got from spring's transaction context.
>>
>> private Map<Method, MapperMethod> mapperMethods = new
>> ConcurrentHashMap<Method, MapperMethod>();
>>
>> public <T> T getMapper(final Class<T> type) {
>>     // mimic iBATIS MapperProxy
>>     return (T)
>> java.lang.reflect.Proxy.newProxyInstance(type.getClassLoader(), new Class[]
>> { type },
>>             new InvocationHandler() {
>>                 @Override
>>                 public Object invoke(final Object proxy, final Method
>> method, final Object[] args) throws Throwable {
>>                     return execute(new SqlSessionCallback<T>() {
>>                         @Override
>>                         public T doInSqlSession(SqlSession sqlSession)
>> throws SQLException {
>>                                // mimic iBATIS MapperProxy
>>                             Class<?> type = method.getDeclaringClass();
>>                                 if
>> (!sqlSession.getConfiguration().hasMapper(type)) {
>>                                 throw new BindingException("Type " + type
>> + " is not known to the MapperRegistry.");
>>                             }
>>
>>                             MapperMethod mm = mapperMethods.get(method);
>>                             if (mm == null) {
>>                                     mm = new MapperMethod(method,
>> sqlSession.getConfiguration());
>>                                     mapperMethods.put(method, mm);
>>                                 } else {
>>                                     logger.debug("Returning a cached
>> mapper method");
>>                                 }
>>
>>                                 return (T) mm.execute(args, sqlSession);
>>                             }
>>                         });
>>                     }
>>                 });
>>     }
>>
>> Or maybe avoid using directly MapperMethods and access to them thought the
>> "standard" api SqlSession.getConfiguration().getMapper(impl, sesion) but in
>> that case caching should be done inside.
>>
>> what do you think about this?
>>
>>
>>
>

Mime
View raw message