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

sf.r2dbc.rowmapper.R2dbcBeanRowMapper Maven / Gradle / Ivy

The newest version!
package sf.r2dbc.rowmapper;

import io.r2dbc.spi.ColumnMetadata;
import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import sf.core.DBObject;
import sf.database.annotations.SmallResults;
import sf.database.listener.EntityListenerManager;
import sf.database.meta.ColumnMapping;
import sf.database.meta.MetaHolder;
import sf.database.meta.TableMapping;
import sf.database.util.OrmValueUtils;
import sf.database.util.SQLUtils;
import sf.r2dbc.sql.R2dbcConvertUtils;
import sf.spring.util.LinkedCaseInsensitiveMap;
import sf.tools.StringUtils;

import javax.persistence.FieldResult;
import java.util.Map;
import java.util.function.Function;

/**
 * 对象转换:
 * 对于子对象,需要使用@Results注解,设置子对象的属性和列名的对应.
 * @param 
 */
public class R2dbcBeanRowMapper implements R2dbcRowMapper {
    private Class beanClass;
    private boolean useTail;//是否使用tail
    private boolean keepUpdate;//是否保留update字段值
    private Function function;

    /**
     * @param beanClass
     */
    public R2dbcBeanRowMapper(Class beanClass) {
        this.beanClass = beanClass;
    }

    /**
     * @param beanClass  实体类
     * @param useTail    是否使用tail
     * @param keepUpdate 是否保留DBObject中的update字段值
     * @param function   回调方法
     */
    public R2dbcBeanRowMapper(Class beanClass, boolean useTail, boolean keepUpdate, Function function) {
        this.beanClass = beanClass;
        this.useTail = useTail;
        this.keepUpdate = keepUpdate;
        this.function = function;
    }

    @Override
    public T apply(Row rs, RowMetadata metadata) {
        try {
            TableMapping table = MetaHolder.getMeta(beanClass);
            T bean = OrmValueUtils.instance(table);
            SmallResults sqlResultSetMapping = beanClass.getAnnotation(SmallResults.class);
            boolean isDBObject = DBObject.class.isAssignableFrom(beanClass);
            if (isDBObject && !keepUpdate) {
                DBObject d = (DBObject) bean;
                //关闭动态插值
                d.stopUpdate();
            }
            for (ColumnMetadata cmd : metadata.getColumnMetadatas()) {
                String columnName = cmd.getName();
                ColumnMapping cm = SQLUtils.getColumnByDBName(table, columnName);
                if (cm != null) {
                    Object value = R2dbcConvertUtils.get(rs.get(columnName), (Class) cmd.getType().getJavaType(), cm);
                    if (/*!cm.getClz().isPrimitive() || */value != null) {
                        //不为基础类型或者 值不为空,则插值
                        OrmValueUtils.setValue(bean, cm, value);
                    }
                    stackFind(rs, sqlResultSetMapping, bean, columnName);
                    continue;
                }

                boolean find = stackFind(rs, sqlResultSetMapping, bean, columnName);

                if (!find && useTail) {
                    //未找到将值设置在tail中.
                    if (isDBObject) {
                        DBObject d = (DBObject) bean;
                        Map map = d.getTail();
                        if (map == null) {
                            map = new LinkedCaseInsensitiveMap<>();
                            d.setTail(map);
                        }
                        map.put(columnName, rs.get(columnName));
                    } else if (table.getTailField() != null) {
                        Map map = OrmValueUtils.getValue(bean, table.getTailField());
                        if (map == null) {
                            map = new LinkedCaseInsensitiveMap<>();
                            OrmValueUtils.setValue(bean, table.getTailField(), map);
                        }
                        map.put(columnName, rs.get(columnName));
                    }
                }
            }
            if (isDBObject && !keepUpdate) {
                DBObject d = (DBObject) bean;
//                d.clearUpdate();
                //开启动态插值
                d.startUpdate();
            }
            if (function != null) {
                bean = function.apply(bean);
            }
            EntityListenerManager.runPostLoad(bean);
            return bean;
        } catch (Exception e) {
            throw new RuntimeException("Can't set bean property.", e);
        }
    }

    /**
     * 迭代查找赋值
     * @param rs
     * @param sqlResultSetMapping
     * @param bean
     * @param columnName
     * @return
     */
    private boolean stackFind(Row rs, SmallResults sqlResultSetMapping, Object bean, String columnName) {
        boolean flag = false;
        if (sqlResultSetMapping != null && sqlResultSetMapping.value().length > 0) {
            FieldResult[] fields = sqlResultSetMapping.value();
            for (int i = 0; i < fields.length; i++) {
                FieldResult fieldResult = fields[i];
                String name = fieldResult.name();
                if (columnName.equals(fieldResult.column())) {
                    String[] fieldNames = StringUtils.split(name, ".");
                    flag = setSubProperties(bean, fieldNames, 0, rs, columnName);
                }
            }
        }
        return flag;
    }

    private boolean setSubProperties(Object bean, String[] fieldPaths, int i, Row rs, String columnName) {
        boolean flag = false;
        String fieldName = fieldPaths[i];
        TableMapping table = MetaHolder.getMeta(bean.getClass());
        ColumnMapping cm = table.getJavaFieldColumnMapping(fieldName);
        if (cm != null) {
            if (fieldPaths.length == 1 || i == fieldPaths.length - 1) {
                Object value = R2dbcConvertUtils.get(rs.get(columnName), null, cm);
                if (value != null) {
                    OrmValueUtils.setValue(bean, cm, value);
                }
                flag = true;
            } else {
                Object obj = null;
                Object innerObj = OrmValueUtils.getValue(bean, cm);
                if (innerObj == null) {
                    obj = OrmValueUtils.instance(MetaHolder.getMeta(cm.getClz()));
                } else {
                    obj = innerObj;
                }
                boolean isDBObject = DBObject.class.isAssignableFrom(cm.getClz());
                if (isDBObject) {
                    DBObject d = (DBObject) obj;
                    //关闭动态插值
                    d.stopUpdate();
                }
                flag = setSubProperties(obj, fieldPaths, i + 1, rs, columnName);
                // 使用set字段方法,非method,可能对某些特殊方法执行不到
                if (innerObj == null) {
                    OrmValueUtils.setValue(bean, cm, obj);
                }
                //清除updateValue
                if (isDBObject) {
                    DBObject d = (DBObject) obj;
                    //开启动态插值
                    d.startUpdate();
                }
            }
        }
        return flag;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy