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.dbutils.DbStringUtils;
import net.dongliu.dbutils.Pair;
import net.dongliu.dbutils.internal.Exceptions;

import javax.annotation.Nonnull;
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) {
        ColumnMapping columnMapping = cls.getAnnotation(ColumnMapping.class);
        boolean toUnderscore = true;
        if (columnMapping != null) {
            toUnderscore = columnMapping.underscore();
        }

        // process bean properties
        Map propertyMap = new HashMap<>();
        PropertyDescriptor[] allProperties;
        try {
            allProperties = Introspector.getBeanInfo(cls).getPropertyDescriptors();
        } catch (IntrospectionException e) {
            throw Exceptions.sneakyThrow(e);
        }
        for (PropertyDescriptor property : allProperties) {
            Method writeMethod = property.getWriteMethod();
            Method readMethod = property.getReadMethod();
            // A Illegal property to mapping to sql result set, should have both getter and setter
            // getClass was filtered by this
            if (writeMethod == null || readMethod == null) {
                continue;
            }

            // set access to true, can improve performance
            writeMethod.setAccessible(true);
            readMethod.setAccessible(true);

            ColumnName columnName = readMethod.getAnnotation(ColumnName.class);
            if (columnName == null) {
                columnName = writeMethod.getAnnotation(ColumnName.class);
            }

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

            }
            propertyMap.put(name, property);
        }

        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()) {
            String name = namedProperty.getKey();
            Object value;
            try {
                value = namedProperty.getValue().getWriteMethod().invoke(bean);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw Exceptions.sneakyThrow(e);
            }
            values.add(Pair.of(name, value));
        }
        return values;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy