![JAR search and dependency download from the Maven repository](/logo.png)
com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactoryUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jbatis Show documentation
Show all versions of jbatis Show documentation
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