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

net.dongliu.dbutils.mapping.BeanMappingUtils Maven / Gradle / Ivy

There is a newer version: 6.0.2
Show newest version
package net.dongliu.dbutils.mapping;

import net.dongliu.commons.collection.Pair;
import net.dongliu.dbutils.StringUtils;
import net.dongliu.dbutils.exception.ReflectionException;

import javax.annotation.Nonnull;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Utils to deal with bean reflection.
 * Only for internal use
 *
 * @author Liu Dong
 */
public class BeanMappingUtils {

    private static final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private static final WeakHashMap, BeanMapping> cache = new WeakHashMap<>();

    /**
     * Get column names this bean should mapping to
     *
     * @param cls The Class to retrieve PropertyDescriptors for.
     */
    @Nonnull
    public static Collection getColumnNames(Class cls) {
        return getBeanMapping(cls).columnNames();
    }

    /**
     * Returns a PropertyDescriptor[] for the given Class.
     *
     * @param cls The Class to retrieve PropertyDescriptors for.
     * @return A PropertyDescriptor[] describing the Class.
     */
    @Nonnull
    public static BeanMapping getBeanMapping(Class cls) {
        BeanMapping beanMapping;
        rwLock.readLock().lock();
        try {
            beanMapping = cache.get(cls);
            if (beanMapping != null) {
                return beanMapping;
            }
        } finally {
            rwLock.readLock().unlock();
        }

        rwLock.writeLock().lock();
        try {
            beanMapping = getBeanMappingNoCache(cls);
            cache.put(cls, beanMapping);
        } finally {
            rwLock.writeLock().unlock();
        }

        return beanMapping;
    }

    private static BeanMapping getBeanMappingNoCache(Class cls) {
        BeanInfo beanInfo;
        try {
            beanInfo = Introspector.getBeanInfo(cls);
        } catch (IntrospectionException e) {
            throw new ReflectionException(e);
        }
        ColumnMapping columnMapping = cls.getAnnotation(ColumnMapping.class);
        boolean toUnderscore = true;
        if (columnMapping != null) {
            toUnderscore = columnMapping.underscore();
        }

        // process bean properties
        Map propertyMap = new HashMap<>();
        PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor descriptor : descriptors) {
            // A Illegal property to mapping to sql result set, should have both getter and setter
            Method setter = descriptor.getWriteMethod();
            if (setter == null) {
                continue;
            }
            Method getter = descriptor.getReadMethod();
            if (getter == null) {
                continue;
            }

            ColumnName columnName = getter.getAnnotation(ColumnName.class);
            if (columnName == null) {
                columnName = setter.getAnnotation(ColumnName.class);
            }

            String name;
            if (columnName != null) {
                name = columnName.value();
            } else {
                name = descriptor.getName();
                if (toUnderscore) {
                    name = StringUtils.camelToUnderscore(name);
                } else {
                    // sql column name is case insensitive, always use low case
                    name = name.toLowerCase();
                }

            }
            propertyMap.put(name, descriptor);
        }

        return new BeanMapping(cls, propertyMap);
    }

    public static List> beanToEntries(Object bean) {
        BeanMapping beanMapping = getBeanMapping(bean.getClass());
        Collection> properties = beanMapping.Properties();
        List> values = new ArrayList<>(properties.size());
        for (Map.Entry namedProperty : beanMapping.Properties()) {
            Method readMethod = namedProperty.getValue().getReadMethod();
            String name = namedProperty.getKey();

            Object value;
            try {
                value = readMethod.invoke(bean);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new ReflectionException(e);
            }
            values.add(Pair.of(name, value));
        }
        return values;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy