added a config property to control defaulting of primitive property when receiving null value from result (SPR-5588)

This commit is contained in:
Thomas Risberg
2009-03-25 15:26:39 +00:00
parent 476a0ed76e
commit 93c56f19df
4 changed files with 144 additions and 6 deletions

View File

@@ -56,7 +56,8 @@ import org.springframework.util.Assert;
* try using column aliases in the SQL statement like "select fname as first_name from customer".
*
* <p>For 'null' values read from the databasem, we will attempt to call the setter, but in the case of
* primitives, this causes a TypeMismatchException. We will trap this exception and log a warning message.
* Java primitives, this causes a TypeMismatchException. This class can be configured (using the
* primitivesDefaultedForNullValue property) to trap this exception and use the primitives default value.
* Be aware that if you use the values from the generated bean to update the database the primitive value
* will have been set to the primitive's default value instead of null.
*
@@ -78,6 +79,9 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
/** Whether we're strictly validating */
private boolean checkFullyPopulated = false;
/** Whether we're defaulting primitives when mapping a null value */
private boolean primitivesDefaultedForNullValue = false;
/** Map of the fields we provide mapping for */
private Map<String, PropertyDescriptor> mappedFields;
@@ -199,6 +203,22 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
return this.checkFullyPopulated;
}
/**
* Set whether we're defaulting Java primitives in the case of mapping a null value from corresponding
* database fields.
* <p>Default is <code>false</code>, throwing an exception when nulls are mapped to Java primitives.
*/
public boolean isPrimitivesDefaultedForNullValue() {
return primitivesDefaultedForNullValue;
}
/**
* Return whether we're defaulting Java primitives in the case of mapping a null value from corresponding
* database fields.
*/
public void setPrimitivesDefaultedForNullValue(boolean primitivesDefaultedForNullValue) {
this.primitivesDefaultedForNullValue = primitivesDefaultedForNullValue;
}
/**
* Extract the values for all columns in the current row.
@@ -229,11 +249,13 @@ public class BeanPropertyRowMapper<T> implements RowMapper<T> {
bw.setPropertyValue(pd.getName(), value);
}
catch (TypeMismatchException e) {
logger.warn("Intercepted TypeMismatchException for row " + rowNumber +
" and column '" + column + "' with value " + value +
" when setting property '" + pd.getName() + "' of type " + pd.getPropertyType() +
" on object: " + mappedObject);
if (value != null) {
if (value == null && primitivesDefaultedForNullValue) {
logger.debug("Intercepted TypeMismatchException for row " + rowNumber +
" and column '" + column + "' with value " + value +
" when setting property '" + pd.getName() + "' of type " + pd.getPropertyType() +
" on object: " + mappedObject);
}
else {
throw e;
}
}

View File

@@ -35,6 +35,10 @@ import org.springframework.jdbc.core.BeanPropertyRowMapper;
* String, boolean, Boolean, byte, Byte, short, Short, int, Integer, long, Long,
* float, Float, double, Double, BigDecimal, <code>java.util.Date</code>, etc.
*
* <p>The mapper can be configured to use the primitives default value when mapping null values by
* passing in 'true' for the 'primitivesDefaultedForNullValue' using the {@link #newInstance(Class, boolean)} method.
* Also see {@link BeanPropertyRowMapper#setPrimitivesDefaultedForNullValue(boolean)}
*
* <p>To facilitate mapping between columns and fields that don't have matching names,
* try using column aliases in the SQL statement like "select fname as first_name from customer".
*
@@ -55,8 +59,19 @@ public class ParameterizedBeanPropertyRowMapper<T> extends BeanPropertyRowMapper
* @param mappedClass the class that each row should be mapped to
*/
public static <T> ParameterizedBeanPropertyRowMapper<T> newInstance(Class<T> mappedClass) {
return newInstance(mappedClass, false);
}
/**
* Static factory method to create a new ParameterizedBeanPropertyRowMapper
* (with the mapped class specified only once).
* @param mappedClass the class that each row should be mapped to
* @param primitivesDefaultedForNullValue whether we're defaulting primitives when mapping a null value
*/
public static <T> ParameterizedBeanPropertyRowMapper<T> newInstance(Class<T> mappedClass, boolean primitivesDefaultedForNullValue) {
ParameterizedBeanPropertyRowMapper<T> newInstance = new ParameterizedBeanPropertyRowMapper<T>();
newInstance.setMappedClass(mappedClass);
newInstance.setPrimitivesDefaultedForNullValue(primitivesDefaultedForNullValue);
return newInstance;
}