Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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 org.apache.commons.dbutils;
 
 import java.util.List;
 import java.util.Map;

BeanProcessor matches column names to bean property names and converts ResultSet columns into objects for those bean properties. Subclasses should override the methods in the processing chain to customize behavior.

This class is thread-safe.

Since:
DbUtils 1.1
See also:
BasicRowProcessor
 
 public class BeanProcessor {

    
Special array value used by mapColumnsToProperties that indicates there is no bean property that matches a column from a ResultSet.
 
     protected static final int PROPERTY_NOT_FOUND = -1;

    
Set a bean's primitive properties to these defaults when SQL NULL is returned. These are the same as the defaults that ResultSet get* methods return in the event of a NULL column.
 
     private static final Map<Class<?>, ObjectprimitiveDefaults = new HashMap<Class<?>, Object>();

    
ResultSet column to bean property name overrides.
 
     private final Map<StringStringcolumnToPropertyOverrides;
 
     static {
         .put(., Integer.valueOf(0));
         .put(., Short.valueOf((short) 0));
         .put(., Byte.valueOf((byte) 0));
         .put(., Float.valueOf(0f));
         .put(., Double.valueOf(0d));
         .put(., Long.valueOf(0L));
         .put(., Character.valueOf((char) 0));
     }

    
Constructor for BeanProcessor.
 
     public BeanProcessor() {
         this(new HashMap<StringString>());
     }

    
Constructor for BeanProcessor configured with column to property name overrides.

Parameters:
columnToPropertyOverrides ResultSet column to bean property name overrides
Since:
1.5
 
     public BeanProcessor(Map<StringStringcolumnToPropertyOverrides) {
         super();
         if (columnToPropertyOverrides == null) {
            throw new IllegalArgumentException("columnToPropertyOverrides map cannot be null");
        }
        this. = columnToPropertyOverrides;
    }

    
Convert a ResultSet row into a JavaBean. This implementation uses reflection and BeanInfo classes to match column names to bean property names. Properties are matched to columns based on several factors:
  1. The class has a writable property with the same name as a column. The name comparison is case insensitive.
  2. The column type can be converted to the property's set method parameter type with a ResultSet.get* method. If the conversion fails (ie. the property was an int and the column was a Timestamp) an SQLException is thrown.

Primitive bean properties are set to their defaults when SQL NULL is returned from the ResultSet. Numeric fields are set to 0 and booleans are set to false. Object bean properties are set to null when SQL NULL is returned. This is the same behavior as the ResultSet get* methods.

Parameters:
<T> The type of bean to create
rs ResultSet that supplies the bean data
type Class from which to create the bean instance
Returns:
the newly created bean
Throws:
java.sql.SQLException if a database access error occurs
    public <T> T toBean(ResultSet rsClass<T> typethrows SQLException {
        PropertyDescriptor[] props = this.propertyDescriptors(type);
        ResultSetMetaData rsmd = rs.getMetaData();
        int[] columnToProperty = this.mapColumnsToProperties(rsmdprops);
        return this.createBean(rstypepropscolumnToProperty);
    }

    
Convert a ResultSet into a List of JavaBeans. This implementation uses reflection and BeanInfo classes to match column names to bean property names. Properties are matched to columns based on several factors:
  1. The class has a writable property with the same name as a column. The name comparison is case insensitive.
  2. The column type can be converted to the property's set method parameter type with a ResultSet.get* method. If the conversion fails (ie. the property was an int and the column was a Timestamp) an SQLException is thrown.

Primitive bean properties are set to their defaults when SQL NULL is returned from the ResultSet. Numeric fields are set to 0 and booleans are set to false. Object bean properties are set to null when SQL NULL is returned. This is the same behavior as the ResultSet get* methods.

Parameters:
<T> The type of bean to create
rs ResultSet that supplies the bean data
type Class from which to create the bean instance
Returns:
the newly created List of beans
Throws:
java.sql.SQLException if a database access error occurs
    public <T> List<T> toBeanList(ResultSet rsClass<T> typethrows SQLException {
        List<T> results = new ArrayList<T>();
        if (!rs.next()) {
            return results;
        }
        PropertyDescriptor[] props = this.propertyDescriptors(type);
        ResultSetMetaData rsmd = rs.getMetaData();
        int[] columnToProperty = this.mapColumnsToProperties(rsmdprops);
        do {
            results.add(this.createBean(rstypepropscolumnToProperty));
        } while (rs.next());
        return results;
    }

    
Creates a new object and initializes its fields from the ResultSet.

Parameters:
<T> The type of bean to create
rs The result set.
type The bean type (the return type of the object).
props The property descriptors.
columnToProperty The column indices in the result set.
Returns:
An initialized object.
Throws:
java.sql.SQLException if a database error occurs.
    private <T> T createBean(ResultSet rsClass<T> type,
            PropertyDescriptor[] propsint[] columnToProperty)
            throws SQLException {
        T bean = this.newInstance(type);
        for (int i = 1; i < columnToProperty.lengthi++) {
            if (columnToProperty[i] == ) {
                continue;
            }
            PropertyDescriptor prop = props[columnToProperty[i]];
            Class<?> propType = prop.getPropertyType();
            Object value = this.processColumn(rsipropType);
            if (propType != null && value == null && propType.isPrimitive()) {
                value = .get(propType);
            }
            this.callSetter(beanpropvalue);
        }
        return bean;
    }

    
Calls the setter method on the target object for the given property. If no setter method exists for the property, this method does nothing.

Parameters:
target The object to set the property on.
prop The property to set.
value The value to pass into the setter.
Throws:
java.sql.SQLException if an error occurs setting the property.
    private void callSetter(Object targetPropertyDescriptor propObject value)
            throws SQLException {
        Method setter = prop.getWriteMethod();
        if (setter == null) {
            return;
        }
        Class<?>[] params = setter.getParameterTypes();
        try {
            // convert types for some popular ones
            if (value instanceof java.util.Date) {
                final String targetType = params[0].getName();
                if ("java.sql.Date".equals(targetType)) {
                    value = new java.sql.Date(((java.util.Datevalue).getTime());
                } else
                if ("java.sql.Time".equals(targetType)) {
                    value = new java.sql.Time(((java.util.Datevalue).getTime());
                } else
                if ("java.sql.Timestamp".equals(targetType)) {
                    value = new java.sql.Timestamp(((java.util.Datevalue).getTime());
                }
            }
            // Don't call setter if the value object isn't the right type
            if (this.isCompatibleType(valueparams[0])) {
                setter.invoke(targetnew Object[]{value});
            } else {
              throw new SQLException(
                  "Cannot set " + prop.getName() + ": incompatible types, cannot convert "
                  + value.getClass().getName() + " to " + params[0].getName());
                  // value cannot be null here because isCompatibleType allows null
            }
        } catch (IllegalArgumentException e) {
            throw new SQLException(
                "Cannot set " + prop.getName() + ": " + e.getMessage());
        } catch (IllegalAccessException e) {
            throw new SQLException(
                "Cannot set " + prop.getName() + ": " + e.getMessage());
        } catch (InvocationTargetException e) {
            throw new SQLException(
                "Cannot set " + prop.getName() + ": " + e.getMessage());
        }
    }

    
ResultSet.getObject() returns an Integer object for an INT column. The setter method for the property might take an Integer or a primitive int. This method returns true if the value can be successfully passed into the setter method. Remember, Method.invoke() handles the unwrapping of Integer into an int.

Parameters:
value The value to be passed into the setter method.
type The setter's parameter type (non-null)
Returns:
boolean True if the value is compatible (null => true)
    private boolean isCompatibleType(Object valueClass<?> type) {
        // Do object check first, then primitives
        if (value == null || type.isInstance(value)) {
            return true;
        } else if (type.equals(.) && Integer.class.isInstance(value)) {
            return true;
        } else if (type.equals(.) && Long.class.isInstance(value)) {
            return true;
        } else if (type.equals(.) && Double.class.isInstance(value)) {
            return true;
        } else if (type.equals(.) && Float.class.isInstance(value)) {
            return true;
        } else if (type.equals(.) && Short.class.isInstance(value)) {
            return true;
        } else if (type.equals(.) && Byte.class.isInstance(value)) {
            return true;
        } else if (type.equals(.) && Character.class.isInstance(value)) {
            return true;
        } else if (type.equals(.) && Boolean.class.isInstance(value)) {
            return true;
        }
        return false;
    }

    
Factory method that returns a new instance of the given Class. This is called at the start of the bean creation process and may be overridden to provide custom behavior like returning a cached bean instance.

Parameters:
<T> The type of object to create
c The Class to create an object from.
Returns:
A newly created object of the Class.
Throws:
java.sql.SQLException if creation failed.
    protected <T> T newInstance(Class<T> cthrows SQLException {
        try {
            return c.newInstance();
        } catch (InstantiationException e) {
            throw new SQLException(
                "Cannot create " + c.getName() + ": " + e.getMessage());
        } catch (IllegalAccessException e) {
            throw new SQLException(
                "Cannot create " + c.getName() + ": " + e.getMessage());
        }
    }

    
Returns a PropertyDescriptor[] for the given Class.

Parameters:
c The Class to retrieve PropertyDescriptors for.
Returns:
A PropertyDescriptor[] describing the Class.
Throws:
java.sql.SQLException if introspection failed.
        throws SQLException {
        // Introspector caches BeanInfo classes for better performance
        BeanInfo beanInfo = null;
        try {
            beanInfo = Introspector.getBeanInfo(c);
        } catch (IntrospectionException e) {
            throw new SQLException(
                "Bean introspection failed: " + e.getMessage());
        }
        return beanInfo.getPropertyDescriptors();
    }

    
The positions in the returned array represent column numbers. The values stored at each position represent the index in the PropertyDescriptor[] for the bean property that matches the column name. If no bean property was found for a column, the position is set to PROPERTY_NOT_FOUND.

Parameters:
rsmd The ResultSetMetaData containing column information.
props The bean property descriptors.
Returns:
An int[] with column index to property index mappings. The 0th element is meaningless because JDBC column indexing starts at 1.
Throws:
java.sql.SQLException if a database access error occurs
    protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,
            PropertyDescriptor[] propsthrows SQLException {
        int cols = rsmd.getColumnCount();
        int[] columnToProperty = new int[cols + 1];
        Arrays.fill(columnToProperty);
        for (int col = 1; col <= colscol++) {
            String columnName = rsmd.getColumnLabel(col);
            if (null == columnName || 0 == columnName.length()) {
              columnName = rsmd.getColumnName(col);
            }
            String propertyName = .get(columnName);
            if (propertyName == null) {
                propertyName = columnName;
            }
            for (int i = 0; i < props.lengthi++) {
                if (propertyName.equalsIgnoreCase(props[i].getName())) {
                    columnToProperty[col] = i;
                    break;
                }
            }
        }
        return columnToProperty;
    }

    
Convert a ResultSet column into an object. Simple implementations could just call rs.getObject(index) while more complex implementations could perform type manipulation to match the column's type to the bean property type.

This implementation calls the appropriate ResultSet getter method for the given property type to perform the type conversion. If the property type doesn't match one of the supported ResultSet types, getObject is called.

Parameters:
rs The ResultSet currently being processed. It is positioned on a valid row before being passed into this method.
index The current column index being processed.
propType The bean property type that this column needs to be converted into.
Returns:
The object from the ResultSet at the given column index after optional type processing or null if the column value was SQL NULL.
Throws:
java.sql.SQLException if a database access error occurs
    protected Object processColumn(ResultSet rsint indexClass<?> propType)
        throws SQLException {
        if ( !propType.isPrimitive() && rs.getObject(index) == null ) {
            return null;
        }
        if (propType.equals(String.class)) {
            return rs.getString(index);
        } else if (
            propType.equals(.) || propType.equals(Integer.class)) {
            return Integer.valueOf(rs.getInt(index));
        } else if (
            propType.equals(.) || propType.equals(Boolean.class)) {
            return Boolean.valueOf(rs.getBoolean(index));
        } else if (propType.equals(.) || propType.equals(Long.class)) {
            return Long.valueOf(rs.getLong(index));
        } else if (
            propType.equals(.) || propType.equals(Double.class)) {
            return Double.valueOf(rs.getDouble(index));
        } else if (
            propType.equals(.) || propType.equals(Float.class)) {
            return Float.valueOf(rs.getFloat(index));
        } else if (
            propType.equals(.) || propType.equals(Short.class)) {
            return Short.valueOf(rs.getShort(index));
        } else if (propType.equals(.) || propType.equals(Byte.class)) {
            return Byte.valueOf(rs.getByte(index));
        } else if (propType.equals(Timestamp.class)) {
            return rs.getTimestamp(index);
        } else if (propType.equals(SQLXML.class)) {
            return rs.getSQLXML(index);
        } else {
            return rs.getObject(index);
        }
    }
New to GrepCode? Check out our FAQ X