View Javadoc
1   /*
2    * Copyright 2004-2025 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.ibatis.sqlmap.engine.mapping.result.loader;
17  
18  import com.ibatis.common.beans.ClassInfo;
19  import com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;
20  import com.ibatis.sqlmap.engine.type.DomTypeMarker;
21  
22  import java.sql.SQLException;
23  import java.util.Collection;
24  import java.util.List;
25  import java.util.Set;
26  
27  import net.sf.cglib.proxy.Enhancer;
28  import net.sf.cglib.proxy.LazyLoader;
29  import net.sf.cglib.proxy.NoOp;
30  
31  /**
32   * Class to lazily load results into objects (uses CGLib to improve performance).
33   */
34  public class EnhancedLazyResultLoader {
35  
36    /** The Constant SET_INTERFACES. */
37    private static final Class[] SET_INTERFACES = { Set.class };
38  
39    /** The Constant LIST_INTERFACES. */
40    private static final Class[] LIST_INTERFACES = { List.class };
41  
42    /** The loader. */
43    private Object loader;
44  
45    /**
46     * Constructor for an enhanced lazy list loader.
47     *
48     * @param client
49     *          - the client that is creating the lazy list
50     * @param statementName
51     *          - the statement to be used to build the list
52     * @param parameterObject
53     *          - the parameter object to be used to build the list
54     * @param targetType
55     *          - the type we are putting data into
56     */
57    public EnhancedLazyResultLoader(SqlMapClientImpl client, String statementName, Object parameterObject,
58        Class targetType) {
59      loader = new EnhancedLazyResultLoaderImpl(client, statementName, parameterObject, targetType);
60    }
61  
62    /**
63     * Loads the result.
64     *
65     * @return the results - a list or object
66     *
67     * @throws SQLException
68     *           if there is a problem
69     */
70    public Object loadResult() throws SQLException {
71      return ((EnhancedLazyResultLoaderImpl) loader).loadResult();
72    }
73  
74    /**
75     * The Class EnhancedLazyResultLoaderImpl.
76     */
77    private static class EnhancedLazyResultLoaderImpl implements LazyLoader {
78  
79      /** The client. */
80      protected SqlMapClientImpl client;
81  
82      /** The statement name. */
83      protected String statementName;
84  
85      /** The parameter object. */
86      protected Object parameterObject;
87  
88      /** The target type. */
89      protected Class targetType;
90  
91      /**
92       * Constructor for an enhanced lazy list loader implementation.
93       *
94       * @param client
95       *          - the client that is creating the lazy list
96       * @param statementName
97       *          - the statement to be used to build the list
98       * @param parameterObject
99       *          - the parameter object to be used to build the list
100      * @param targetType
101      *          - the type we are putting data into
102      */
103     public EnhancedLazyResultLoaderImpl(SqlMapClientImpl client, String statementName, Object parameterObject,
104         Class targetType) {
105       this.client = client;
106       this.statementName = statementName;
107       this.parameterObject = parameterObject;
108       this.targetType = targetType;
109     }
110 
111     /**
112      * Loads the result.
113      *
114      * @return the results - a list or object
115      *
116      * @throws SQLException
117      *           if there is a problem
118      */
119     public Object loadResult() throws SQLException {
120       if (DomTypeMarker.class.isAssignableFrom(targetType)) {
121         return ResultLoader.getResult(client, statementName, parameterObject, targetType);
122       }
123       if (Collection.class.isAssignableFrom(targetType)) {
124         if (Set.class.isAssignableFrom(targetType)) {
125           return Enhancer.create(Object.class, SET_INTERFACES, this);
126         }
127         return Enhancer.create(Object.class, LIST_INTERFACES, this);
128       }
129       if (targetType.isArray() || ClassInfo.isKnownType(targetType)) {
130         return ResultLoader.getResult(client, statementName, parameterObject, targetType);
131       }
132       return Enhancer.create(targetType, this);
133     }
134 
135     @Override
136     public Object loadObject() throws Exception {
137       try {
138         Object result = ResultLoader.getResult(client, statementName, parameterObject, targetType);
139         if (result == null) {
140           // if no result is available return a proxy with a default object is returned
141           // because the loadObject() method must not return null
142           result = Enhancer.create(targetType, NoOp.INSTANCE);
143         }
144         return result;
145       } catch (SQLException e) {
146         throw new RuntimeException("Error lazy loading result. Cause: " + e, e);
147       }
148     }
149   }
150 
151 }