All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactoryUtil Maven / Gradle / Ivy

Go to download

The jBATIS persistence framework will help you to significantly reduce the amount of Java code that you normally need to access a relational database. iBATIS simply maps JavaBeans to SQL statements using a very simple XML descriptor.

The newest version!
/*
 *  Copyright 2006 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.ibatis.sqlmap.engine.mapping.result;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import com.ibatis.common.resources.Resources;

/**
 * This class is used to create instances of result objects. It will use the configured ResultObjectFactory if there is
 * one, otherwise it will use iBATIS' normal methods.
 * 
 * Note that this class is somewhat tightly coupled with SqlExecuter - SqlExecute must call the setStatementId() and
 * setResultObjectFactory() methods before executing a statement. This is a result of using a ThreadLocal to hold the
 * current configuration for the statement under execution. Using a ThreadLocal is a solution for IBATIS-366. Without a
 * ThreadLocal, the current factory and statement id would have to be added to many method signatures - often in
 * inappropriate places.
 * 
 * @author Jeff Butler
 */
public class ResultObjectFactoryUtil {

    /**
     * Use a ThreadLocal to hold the current statementId and factory. This is much easier than passing these items all
     * over the place, and it has no measurable impact on performance (I did a test with 100000 result rows and found no
     * impact - Jeff Butler).
     */
    private static ThreadLocal> factorySettings = new ThreadLocal>();

    /**
     * Utility class - no instances
     */
    private ResultObjectFactoryUtil() {
        super();
    }

    /**
     * Algorithm:
     * 
     * 
    *
  • If factory is null, then create object internally()
  • *
  • Otherwise try to create object through factory
  • *
  • If null returned from factory, then create object internally
  • *
* * This allows the factory to selectively create objects, also allows for the common possibility that a factory is * not configured. * * @param factory * the factory to use. May be null! * @param statementId * the ID of the statement that generated the call to this method * @param clazz * the type of object to create * @return a new instance of the specified class. The instance must be castable to the specified class. * @throws InstantiationException * if the instance cannot be created. If you throw this Exception, iBATIS will throw a runtime exception * in response and will end. * @throws IllegalAccessException * if the constructor cannot be accessed. If you throw this Exception, iBATIS will throw a runtime * exception in response and will end. */ public static Object createObjectThroughFactory(Class clazz) throws InstantiationException, IllegalAccessException { FactorySettings fs = getCurrentFactorySettings(); Object obj; if (fs.getResultObjectFactory() == null) { obj = createObjectInternally(clazz); } else { obj = fs.getResultObjectFactory().createInstance(fs.getStatementId(), clazz); if (obj == null) { obj = createObjectInternally(clazz); } } return obj; } /** * This method creates object using iBATIS' normal mechanism. We translate List and Collection to ArrayList, and Set * to HashSet because these interfaces may be requested in nested resultMaps and we want to supply default * implementations. * * @param clazz * @return * @throws InstantiationException * @throws IllegalAccessException */ private static Object createObjectInternally(Class clazz) throws InstantiationException, IllegalAccessException { Class classToCreate; if (clazz == List.class || clazz == Collection.class) { classToCreate = ArrayList.class; } else if (clazz == Set.class) { classToCreate = LinkedHashSet.class; } else { classToCreate = clazz; } Object obj = Resources.instantiate(classToCreate); return obj; } /** * This method pushes a new result object factory configuration onto the stack. We use a stack because the method * can be called in a "nested" fashion if there are sub-selects. Calls to this method should be equally balanced * with calls to cleanupResultObjectFactory(). * * @param resultObjectFactory * @param statementId */ public static void setupResultObjectFactory(ResultObjectFactory resultObjectFactory, String statementId) { Stack fss = (Stack) factorySettings.get(); if (fss == null) { fss = new Stack(); factorySettings.set(fss); } FactorySettings fs = new FactorySettings(); fs.setResultObjectFactory(resultObjectFactory); fs.setStatementId(statementId); fss.push(fs); } /** * Removes the FactorySettings bound to the current thread to avoid classloader leak issues. This method pops the * top item off the stack, and kills the stack if there are no items left. */ public static void cleanupResultObjectFactory() { Stack fss = (Stack) factorySettings.get(); if (!fss.empty()) { fss.pop(); } if (fss.empty()) { factorySettings.remove(); } } private static FactorySettings getCurrentFactorySettings() { Stack fss = (Stack) factorySettings.get(); FactorySettings fs; if (fss == null || fss.empty()) { // this shouldn't happen if the SqlExecuter is behaving correctly fs = new FactorySettings(); } else { fs = fss.peek(); } return fs; } private static class FactorySettings { private ResultObjectFactory resultObjectFactory; private String statementId; public ResultObjectFactory getResultObjectFactory() { return resultObjectFactory; } public void setResultObjectFactory(ResultObjectFactory resultObjectFactory) { this.resultObjectFactory = resultObjectFactory; } public String getStatementId() { return statementId; } public void setStatementId(String statementId) { this.statementId = statementId; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy