JdbcKit.java
package space.sunqian.fs.utils.jdbc;
import space.sunqian.annotation.Immutable;
import space.sunqian.annotation.Nonnull;
import space.sunqian.fs.Fs;
import space.sunqian.fs.base.option.Option;
import space.sunqian.fs.base.string.NameFormatter;
import space.sunqian.fs.base.string.NameMapper;
import space.sunqian.fs.object.convert.ObjectConverter;
import space.sunqian.fs.reflect.TypeRef;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Utilities for JDBC and SQL.
*
* @author sunqian
*/
public class JdbcKit {
/**
* Return the default name mapper to map the column name to the field name of the element type. The default name
* mapper assume the column name is in underscore case (e.g. {@code USER_ID}) and the field name is in lower camel
* case (e.g. {@code userId}).
*
* @return the default name mapper
*/
public static @Nonnull NameMapper defaultNameMapper() {
return DbNameMapper.INST;
}
/**
* Convert the result set to a list of objects, using {@link #defaultNameMapper()} and
* }{@link ObjectConverter#defaultConverter()} to convert the object of the JDBC type to the java type.
*
* @param resultSet the result set
* @param javaType the element java type of the returned list
* @param <T> the element type of the returned list
* @return the row list of the result set of which each row is mapped to the type {@link T}
* @throws SqlRuntimeException if any error occurs
*/
public static <T> @Immutable @Nonnull List<@Nonnull T> toObject(
@Nonnull ResultSet resultSet,
@Nonnull Class<T> javaType
) throws SqlRuntimeException {
return toObject(
resultSet,
javaType,
defaultNameMapper()
);
}
/**
* Convert the result set to a list of objects, using {@link #defaultNameMapper()} and
* {@link ObjectConverter#defaultConverter()} to convert the object of the JDBC type to the java type.
*
* @param resultSet the result set
* @param javaType the element java type reference of the returned list
* @param <T> the element type of the returned list
* @return the row list of the result set of which each row is mapped to the type {@link T}
* @throws SqlRuntimeException if any error occurs
*/
public static <T> @Immutable @Nonnull List<@Nonnull T> toObject(
@Nonnull ResultSet resultSet,
@Nonnull TypeRef<T> javaType
) throws SqlRuntimeException {
return toObject(
resultSet,
javaType,
defaultNameMapper()
);
}
/**
* Convert the result set to a list of objects, using {@link #defaultNameMapper()} and
* {@link ObjectConverter#defaultConverter()} to convert the object of the JDBC type to the java type.
*
* @param resultSet the result set
* @param javaType the element java type of the returned list
* @return the row list of the result set of which each row is mapped to the specified java type
* @throws SqlRuntimeException if any error occurs
*/
public static @Immutable @Nonnull List<@Nonnull Object> toObject(
@Nonnull ResultSet resultSet,
@Nonnull Type javaType
) throws SqlRuntimeException {
return toObject(
resultSet,
javaType,
defaultNameMapper()
);
}
/**
* Convert the result set to a list of objects, using {@link ObjectConverter#defaultConverter()} to convert the
* object of the JDBC type to the java type.
*
* @param resultSet the result set
* @param javaType the element java type of the returned list
* @param nameMapper the name mapper to map the column name to the field name of the element type
* @param <T> the element type of the returned list
* @return the row list of the result set of which each row is mapped to the type {@link T}
* @throws SqlRuntimeException if any error occurs
*/
public static <T> @Immutable @Nonnull List<@Nonnull T> toObject(
@Nonnull ResultSet resultSet,
@Nonnull Class<T> javaType,
@Nonnull NameMapper nameMapper
) throws SqlRuntimeException {
return toObject(
resultSet,
javaType,
nameMapper,
ObjectConverter.defaultConverter()
);
}
/**
* Convert the result set to a list of objects, using {@link ObjectConverter#defaultConverter()} to convert the
* object of the JDBC type to the java type.
*
* @param resultSet the result set
* @param javaTypeRef the element java type reference of the returned list
* @param nameMapper the name mapper to map the column name to the field name of the element type
* @param <T> the element type of the returned list
* @return the row list of the result set of which each row is mapped to the type {@link T}
* @throws SqlRuntimeException if any error occurs
*/
public static <T> @Immutable @Nonnull List<@Nonnull T> toObject(
@Nonnull ResultSet resultSet,
@Nonnull TypeRef<T> javaTypeRef,
@Nonnull NameMapper nameMapper
) throws SqlRuntimeException {
return toObject(
resultSet,
javaTypeRef,
nameMapper,
ObjectConverter.defaultConverter()
);
}
/**
* Convert the result set to a list of objects, using {@link ObjectConverter#defaultConverter()} to convert the
* object of the JDBC type to the java type.
*
* @param resultSet the result set
* @param javaType the element java type of the returned list
* @param nameMapper the name mapper to map the column name to the field name of the element type
* @return the row list of the result set of which each row is mapped to the specified java type
* @throws SqlRuntimeException if any error occurs
*/
public static @Immutable @Nonnull List<@Nonnull Object> toObject(
@Nonnull ResultSet resultSet,
@Nonnull Type javaType,
@Nonnull NameMapper nameMapper
) throws SqlRuntimeException {
return toObject(
resultSet,
javaType,
nameMapper,
ObjectConverter.defaultConverter()
);
}
/**
* Convert the result set to a list of objects.
*
* @param resultSet the result set
* @param javaType the element java type of the returned list
* @param nameMapper the name mapper to map the column name to the field name of the element type
* @param converter the converter to convert the object of the JDBC type to the java type
* @param options the options for converting
* @param <T> the element type of the returned list
* @return the row list of the result set of which each row is mapped to the type {@link T}
* @throws SqlRuntimeException if any error occurs
*/
public static <T> @Immutable @Nonnull List<@Nonnull T> toObject(
@Nonnull ResultSet resultSet,
@Nonnull Class<T> javaType,
@Nonnull NameMapper nameMapper,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... options
) throws SqlRuntimeException {
return Fs.as(toObject(resultSet, (Type) javaType, nameMapper, converter, options));
}
/**
* Convert the result set to a list of objects.
*
* @param resultSet the result set
* @param javaTypeRef the element java type reference of the returned list
* @param nameMapper the name mapper to map the column name to the field name of the element type
* @param converter the converter to convert the object of the JDBC type to the java type
* @param options the options for converting
* @param <T> the element type of the returned list
* @return the row list of the result set of which each row is mapped to the type {@link T}
* @throws SqlRuntimeException if any error occurs
*/
public static <T> @Immutable @Nonnull List<@Nonnull T> toObject(
@Nonnull ResultSet resultSet,
@Nonnull TypeRef<T> javaTypeRef,
@Nonnull NameMapper nameMapper,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... options
) throws SqlRuntimeException {
return Fs.as(toObject(resultSet, javaTypeRef.type(), nameMapper, converter, options));
}
/**
* Convert the result set to a list of objects.
*
* @param resultSet the result set
* @param javaType the element java type of the returned list
* @param nameMapper the name mapper to map the column name to the field name of the element type
* @param converter the converter to convert the object of the JDBC type to the java type
* @param options the options for converting
* @return the row list of the result set of which each row is mapped to the specified java type
* @throws SqlRuntimeException if any error occurs
*/
public static @Immutable @Nonnull List<@Nonnull Object> toObject(
@Nonnull ResultSet resultSet,
@Nonnull Type javaType,
@Nonnull NameMapper nameMapper,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... options
) throws SqlRuntimeException {
return Fs.uncheck(() -> resultToObject(resultSet, javaType, nameMapper, converter, options), SqlRuntimeException::new);
}
private static <T> @Immutable @Nonnull List<@Nonnull T> resultToObject(
@Nonnull ResultSet resultSet,
@Nonnull Type javaType,
@Nonnull NameMapper nameMapper,
@Nonnull ObjectConverter converter,
@Nonnull Option<?, ?> @Nonnull ... options
) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
ArrayList<T> objects = new ArrayList<>();
Map<String, Object> rowMap = new HashMap<>();
while (resultSet.next()) {
for (int column = 0; column < metaData.getColumnCount(); column++) {
String columnName = metaData.getColumnName(column + 1);
Object jdbcObject = resultSet.getObject(column + 1);
String fieldName = nameMapper.map(columnName);
rowMap.put(fieldName, jdbcObject);
}
Object element = converter.convert(rowMap, javaType, options);
objects.add(Fs.as(element));
rowMap.clear();
}
objects.trimToSize();
return objects;
}
private enum DbNameMapper implements NameMapper {
INST;
private final @Nonnull NameFormatter from = NameFormatter.delimiter("_");
private final @Nonnull NameFormatter to = NameFormatter.lowerCamel();
@Override
public @Nonnull String map(@Nonnull String name) {
String lowerName = name.toLowerCase();
return from.format(lowerName, to);
}
}
private JdbcKit() {
}
}