ibatis-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Oleg Shpak <o...@rap-x.com>
Subject Proxy target type for Lazy loading
Date Thu, 11 Aug 2005 13:39:44 GMT

I'm having a problem with iBatis which I'm keen to solve by patching
iBatis (other solutions exist, but they are a bit cumbersome).

In short, I propose to modify loadResult() method in
so that is creates more "honest" proxies, proxies which base on lazy
loading statement's resultMap result class, rather than just on method
return type.
    public Object loadResult() throws SQLException {
      if (DomTypeMarker.class.isAssignableFrom(targetType)) {
        return ResultLoader.getResult(client, statementName,
parameterObject, targetType);
      } else if (Collection.class.isAssignableFrom(targetType)) {
        return Enhancer.create(Object.class, INTERFACES, this);
      } else if (targetType.isArray() ||
ClassInfo.isKnownType(targetType)) {
        return ResultLoader.getResult(client, statementName,
parameterObject, targetType);
      } else {
        // NEW CODE STARTS
        Class type;
        try {
            ResultMap resultMap =
            type = resultMap.getResultClass();
        } catch (SqlMapException e) {
            type = targetType;
        return Enhancer.create(type, this);
        // NEW CODE ENDS
        // old code was
       //   return Enhancer.create(targetType, this);

The problem

When a proxy is created for an object, target type is determined using
the property method return type. It is possible that the actual return
value of a method is a subclass of the return type (especially if the
return type is an interface).

// public interfaces
interface A {...}

interface B {
    A getA();

// implementation classes
class A1 implements A { ...}
class B1 implements B {
    private A1 a;
    public A getA(){
       return a; //an instance of A1

// result maps

<resultMap id="A" class="A1">
<resultMap id="B" class="B1">
   <result property="a" column="a_id" select="getA"/>

<select id="getA" resultMap="A">

Here I configured lazy loading for B1.getA. The proxy which is being
generated is based on type A, not on type A1. My DAO class for type A
actually returns instances of type A1. Generally it is OK for it (DAO
class) to consume objects of type A, but in some cases, when it needs to
modify some implementation details it has to cast them down to A1. This
is where proxies cause a ClassCastException. "Honest" proxies don't.

What do you think?
Probably I put my code not into the right place, or it, probably, should
be optionally turned on/off.


View raw message