/*
* Copyright 2002-2009 the original author or authors.
*
* 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 org.springframework.dao.support;
import java.util.Collection;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.dao.TypeMismatchDataAccessException;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.NumberUtils;
/**
* Miscellaneous utility methods for DAO implementations.
* Useful with any data access technology.
*
* @author Juergen Hoeller
* @since 1.0.2
*/
public abstract class DataAccessUtils {
/**
* Return a single result object from the given Collection.
* <p>Returns <code>null</code> if 0 result objects found;
* throws an exception if more than 1 element found.
* @param results the result Collection (can be <code>null</code>)
* @return the single result object, or <code>null</code> if none
* @throws IncorrectResultSizeDataAccessException if more than one
* element has been found in the given Collection
*/
public static <T> T singleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
return null;
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
/**
* Return a single result object from the given Collection.
* <p>Throws an exception if 0 or more than 1 element found.
* @param results the result Collection (can be <code>null</code>)
* @return the single result object
* @throws IncorrectResultSizeDataAccessException if more than one
* element has been found in the given Collection
* @throws EmptyResultDataAccessException if no element at all
* has been found in the given Collection
*/
public static <T> T requiredSingleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
/**
* Return a unique result object from the given Collection.
* <p>Returns <code>null</code> if 0 result objects found;
* throws an exception if more than 1 instance found.
* @param results the result Collection (can be <code>null</code>)
* @return the unique result object, or <code>null</code> if none
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @see org.springframework.util.CollectionUtils#hasUniqueObject
*/
public static <T> T uniqueResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
return null;
}
if (!CollectionUtils.hasUniqueObject(results)) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
/**
* Return a unique result object from the given Collection.
* <p>Throws an exception if 0 or more than 1 instance found.
* @param results the result Collection (can be <code>null</code>)
* @return the unique result object
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @throws EmptyResultDataAccessException if no result object at all
* has been found in the given Collection
* @see org.springframework.util.CollectionUtils#hasUniqueObject
*/
public static <T> T requiredUniqueResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
}
if (!CollectionUtils.hasUniqueObject(results)) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
/**
* Return a unique result object from the given Collection.
* Throws an exception if 0 or more than 1 result objects found,
* of if the unique result object is not convertable to the
* specified required type.
* @param results the result Collection (can be <code>null</code>)
* @return the unique result object
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @throws EmptyResultDataAccessException if no result object
* at all has been found in the given Collection
* @throws TypeMismatchDataAccessException if the unique object does
* not match the specified required type
*/
@SuppressWarnings("unchecked")
public static <T> T objectResult(Collection<?> results, Class<T> requiredType)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
Object result = requiredUniqueResult(results);
if (requiredType != null && !requiredType.isInstance(result)) {
if (String.class.equals(requiredType)) {
result = result.toString();
}
else if (Number.class.isAssignableFrom(requiredType) && Number.class.isInstance(result)) {
try {
result = NumberUtils.convertNumberToTargetClass(((Number) result), (Class<? extends Number>) requiredType);
}
catch (IllegalArgumentException ex) {
throw new TypeMismatchDataAccessException(ex.getMessage());
}
}
else {
throw new TypeMismatchDataAccessException(
"Result object is of type [" + result.getClass().getName() +
"] and could not be converted to required type [" + requiredType.getName() + "]");
}
}
return (T) result;
}
/**
* Return a unique int result from the given Collection.
* Throws an exception if 0 or more than 1 result objects found,
* of if the unique result object is not convertable to an int.
* @param results the result Collection (can be <code>null</code>)
* @return the unique int result
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @throws EmptyResultDataAccessException if no result object
* at all has been found in the given Collection
* @throws TypeMismatchDataAccessException if the unique object
* in the collection is not convertable to an int
*/
public static int intResult(Collection results)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
return objectResult(results, Number.class).intValue();
}
/**
* Return a unique long result from the given Collection.
* Throws an exception if 0 or more than 1 result objects found,
* of if the unique result object is not convertable to a long.
* @param results the result Collection (can be <code>null</code>)
* @return the unique long result
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @throws EmptyResultDataAccessException if no result object
* at all has been found in the given Collection
* @throws TypeMismatchDataAccessException if the unique object
* in the collection is not convertable to a long
*/
public static long longResult(Collection results)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
return objectResult(results, Number.class).longValue();
}
/**
* Return a translated exception if this is appropriate,
* otherwise return the input exception.
* @param rawException exception we may wish to translate
* @param pet PersistenceExceptionTranslator to use to perform the translation
* @return a translated exception if translation is possible, or
* the raw exception if it is not
*/
public static RuntimeException translateIfNecessary(
RuntimeException rawException, PersistenceExceptionTranslator pet) {
Assert.notNull(pet, "PersistenceExceptionTranslator must not be null");
DataAccessException dex = pet.translateExceptionIfPossible(rawException);
return (dex != null ? dex : rawException);
}
}
|