All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dongliu.dbutils.handlers.BeanRowProcessor Maven / Gradle / Ivy

package net.dongliu.dbutils.handlers;

import net.dongliu.commons.reflect.BeanProperty;
import net.dongliu.commons.reflect.ClassConstructor;
import net.dongliu.commons.reflect.JavaClass;
import net.dongliu.dbutils.RowProcessor;
import net.dongliu.dbutils.mapping.BeanMapping;
import net.dongliu.dbutils.mapping.BeanMappingUtils;

import java.sql.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

/**
 * 

* BeanRowProcessor 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 not thread-safe. *

*/ public class BeanRowProcessor implements RowProcessor { private final Class type; private final ClassConstructor constructor; /** * ResultSet column to bean property name overrides. */ private final Map columnToPropertyOverrides; /** * column start with index 1 */ private BeanProperty[] columnToProperty; /** * Constructor for BeanRowProcessor. */ public BeanRowProcessor(Class type) { this(type, Collections.emptyMap()); } /** * Constructor for BeanRowProcessor configured with column to property name overrides. * * @param columnToPropertyOverrides ResultSet column to bean property name overrides */ public BeanRowProcessor(Class type, Map columnToPropertyOverrides) { this.type = type; this.columnToPropertyOverrides = Objects.requireNonNull(columnToPropertyOverrides); this.constructor = JavaClass.of(type).getConstructor(); } private void init(ResultSet rs) throws SQLException { BeanMapping beanMapping = BeanMappingUtils.getBeanMapping(type); ResultSetMetaData rsmd = rs.getMetaData(); this.columnToProperty = this.mapColumnsToProperties(rsmd, beanMapping); } @Override public T convert(ResultSet rs, int row) throws SQLException { if (row == 1) { init(rs); } T bean = constructor.construct(); for (int i = 1; i < columnToProperty.length; i++) { BeanProperty property = columnToProperty[i]; this.processColumn(rs, i, bean, property); } return bean; } /** * Map resultSet columns to bean properties * * @param metaData The ResultSetMetaData containing column information. * @throws SQLException if a database access error occurs */ private BeanProperty[] mapColumnsToProperties(ResultSetMetaData metaData, BeanMapping beanMapping) throws SQLException { final int count = metaData.getColumnCount(); final BeanProperty[] properties = new BeanProperty[count + 1]; for (int col = 1; col <= count; col++) { String columnName = metaData.getColumnLabel(col); if (columnName == null || columnName.isEmpty()) { columnName = metaData.getColumnName(col); } String propertyName = columnName.toLowerCase(); String overrideName = columnToPropertyOverrides.get(propertyName); if (overrideName != null) { propertyName = overrideName; } BeanProperty property = beanMapping.getProperty(propertyName); if (property == null) { throw new SQLException("Bean property not found for column " + columnName + ", mapping to: " + propertyName); } properties[col] = property; } return properties; } /** * 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. *

* * @param rs The ResultSet currently being processed. It is * positioned on a valid row before being passed into this method. * @param index The current column index being processed. * @throws SQLException if a database access error occurs */ private void processColumn(ResultSet rs, int index, Object bean, BeanProperty property) throws SQLException { Class propertyType = property.type(); if (propertyType == String.class) { property.set(bean, rs.getString(index)); } else if (propertyType == int.class) { property.setInt(bean, rs.getInt(index)); } else if (propertyType == boolean.class) { property.setBoolean(bean, rs.getBoolean(index)); } else if (propertyType == long.class) { property.setLong(bean, rs.getLong(index)); } else if (propertyType == double.class) { property.setDouble(bean, rs.getDouble(index)); } else if (propertyType == float.class) { property.setFloat(bean, rs.getFloat(index)); } else if (propertyType == short.class) { property.setShort(bean, rs.getShort(index)); } else if (propertyType == byte.class) { property.setByte(bean, rs.getByte(index)); } else if (propertyType == byte[].class) { property.set(bean, rs.getBytes(index)); } else if (propertyType == Timestamp.class) { property.set(bean, rs.getTimestamp(index)); } else if (propertyType == Integer.class) { int value = rs.getInt(index); if (rs.wasNull()) { property.set(bean, null); } else { property.set(bean, value); } } else if (propertyType == Boolean.class) { boolean value = rs.getBoolean(index); if (rs.wasNull()) { property.set(bean, null); } else { property.set(bean, value); } } else if (propertyType == Long.class) { long value = rs.getLong(index); if (rs.wasNull()) { property.set(bean, null); } else { property.set(bean, value); } } else if (propertyType == Double.class) { double value = rs.getDouble(index); if (rs.wasNull()) { property.set(bean, null); } else { property.set(bean, value); } } else if (propertyType == Float.class) { float value = rs.getFloat(index); if (rs.wasNull()) { property.set(bean, null); } else { property.set(bean, value); } } else if (propertyType == Short.class) { short value = rs.getShort(index); if (rs.wasNull()) { property.set(bean, null); } else { property.set(bean, value); } } else if (propertyType == byte.class) { byte value = rs.getByte(index); if (rs.wasNull()) { property.set(bean, null); } else { property.set(bean, value); } } else if (propertyType == Timestamp.class) { property.set(bean, rs.getTimestamp(index)); } else if (propertyType == java.sql.Date.class) { property.set(bean, rs.getDate(index)); } else if (propertyType == java.sql.Time.class) { property.set(bean, rs.getTime(index)); } else if (propertyType == SQLXML.class) { property.set(bean, rs.getSQLXML(index)); } else if (propertyType.getClass().isEnum()) { String str = rs.getString(index); if (str == null) { property.set(bean, null); } else { property.set(bean, Enum.valueOf(propertyType.asSubclass(Enum.class), str)); } } else if (propertyType == Instant.class) { Timestamp timestamp = rs.getTimestamp(index); if (timestamp != null) { property.set(bean, timestamp.toInstant()); } else { property.set(bean, null); } } else if (propertyType == LocalDateTime.class) { Timestamp timestamp = rs.getTimestamp(index); if (timestamp != null) { property.set(bean, timestamp.toLocalDateTime()); } else { property.set(bean, null); } } else if (propertyType == LocalDate.class) { Date date = rs.getDate(index); if (date != null) { property.set(bean, date.toLocalDate()); } else { property.set(bean, null); } } else if (propertyType == LocalTime.class) { Time time = rs.getTime(index); if (time != null) { property.set(bean, time.toLocalTime()); } else { property.set(bean, null); } } else { Object value = rs.getObject(index); property.set(bean, value); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy