ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Clinton Begin <clinton.be...@gmail.com>
Subject Re: MapperMethod caching?
Date Fri, 01 Jan 2010 16:05:08 GMT
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