Author: dfabulich Date: Tue Feb 10 07:20:16 2009 New Revision: 742870 URL: http://svn.apache.org/viewvc?rev=742870&view=rev Log: [DBUTILS-29] Support bean property to SQL IN parameter mapping
Defines new fillStatementWithBean functions, and makes fillStatement public Modified: commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java Modified: commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java URL: http://svn.apache.org/viewvc/commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java?rev=742870&r1=742869&r2=742870&view=diff ============================================================================== --- commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java (original) +++ commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java Tue Feb 10 07:20:16 2009 @@ -16,6 +16,9 @@ */ package org.apache.commons.dbutils; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; import java.sql.Connection; import java.sql.ParameterMetaData; import java.sql.PreparedStatement; @@ -157,7 +160,7 @@ * value to pass in. * @throws SQLException if a database access error occurs */ - protected void fillStatement(PreparedStatement stmt, Object[] params) + public void fillStatement(PreparedStatement stmt, Object[] params) throws SQLException { if (params == null) { @@ -190,6 +193,87 @@ } /** + * Fill the <code>PreparedStatement</code> replacement parameters with the + * given object's bean property values. + * + * @param stmt + * PreparedStatement to fill + * @param bean + * a JavaBean object + * @param properties + * an ordered array of properties; this gives the order to insert + * values in the statement + * @throws SQLException + * if a database access error occurs + */ + public void fillStatementWithBean(PreparedStatement stmt, Object bean, + PropertyDescriptor[] properties) throws SQLException { + Object[] params = new Object[properties.length]; + for (int i = 0; i < properties.length; i++) { + PropertyDescriptor property = properties[i]; + Object value = null; + try { + if (property.getReadMethod().getParameterTypes().length > 0) { + throw new SQLException( + "Can't use an indexed bean property as a SQL parameter: " + + property.getName()); + } + value = property.getReadMethod().invoke(bean, new Object[0]); + } catch (Exception e) { + throw new RuntimeException(e); + } + params[i] = value; + } + fillStatement(stmt, params); + } + + /** + * Fill the <code>PreparedStatement</code> replacement parameters with the + * given object's bean property values. + * + * @param stmt + * PreparedStatement to fill + * @param bean + * a JavaBean object + * @param propertyNames + * an ordered array of property names (these should match the + * getters/setters); this gives the order to insert values in the + * statement + * @throws SQLException + * if a database access error occurs + */ + public void fillStatementWithBean(PreparedStatement stmt, Object bean, + String[] propertyNames) throws SQLException { + PropertyDescriptor[] descriptors; + try { + descriptors = Introspector.getBeanInfo(bean.getClass()) + .getPropertyDescriptors(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + PropertyDescriptor[] sorted = new PropertyDescriptor[propertyNames.length]; + for (int i = 0; i < propertyNames.length; i++) { + String propertyName = propertyNames[i]; + if (propertyName == null) + throw new NullPointerException("propertyName can't be null: " + + i); + boolean found = false; + for (int j = 0; j < descriptors.length; j++) { + PropertyDescriptor descriptor = descriptors[j]; + if (propertyName.equals(descriptor.getName())) { + sorted[i] = descriptor; + found = true; + break; + } + } + if (!found) + throw new RuntimeException("Couldn't find bean property: " + + bean.getClass() + " " + propertyName); + } + fillStatementWithBean(stmt, bean, sorted); + } + + /** * Returns the <code>DataSource</code> this runner is using. * <code>QueryRunner</code> methods always call this method to get the * <code>DataSource</code> so subclasses can provide specialized