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

cn.woodwhales.common.util.datasource.DataSourceTool Maven / Gradle / Ivy

There is a newer version: 3.8.3
Show newest version
package cn.woodwhales.common.util.datasource;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.reflect.FieldUtils;

import javax.persistence.Column;
import javax.persistence.Table;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.sql.*;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;

/**
 * @author woodwhales on 2021-01-28 21:22
 * 数据库查询工具
 */
@Slf4j
public class DataSourceTool {

    private String driverClass;
    private String url;
    private String username;
    private String password;
    private Connection connection;
    private Map, TargetInfo> targetInfoCache = new HashMap<>(16);
    private Map, Function> annotationCache = new HashMap<>(16);

    public static DataSourceTool newMysql(String url, String username, String password) {
        return new DataSourceTool("com.mysql.jdbc.Driver", url, username, password);
    }

    public static DataSourceTool newMysql8(String url, String username, String password) {
        return new DataSourceTool("com.mysql.cj.jdbc.Driver", url, username, password);
    }

    public static DataSourceTool newOracle(String url, String username, String password) {
        return new DataSourceTool("oracle.jdbc.OracleDriver", url, username, password);
    }

    public  DataSourceTool(String driverClass, String url, String username, String password) {
        this.driverClass = driverClass;
        this.url = url;
        this.username = username;
        this.password = password;

        try {
            Class.forName(this.driverClass);
            Connection connection = DriverManager.getConnection(this.url, this.username, this.password);
            this.connection = connection;
        } catch (Exception e) {
            Throwable cause = e.getCause();
            if(cause instanceof SQLException){
                SQLException sqlException = (SQLException) cause;
                String sqlState = sqlException.getSQLState();
                if("28000".equals(sqlState)) {
                    System.out.println("数据库账号或密码错误!!!");
                }
            } else {
                e.printStackTrace();
            }
            System.exit(0);
        }

    }

    public  List queryList(String sql,
                                       Class clazz,
                                       Class annotationClass,
                                       Function function) throws Exception {

        return queryList(sql, this.getTarget(clazz, annotationClass, function));
    }

    private  TargetInfo cacheTarget(Class clazz,
                                                                   Class annotationClass,
                                                                   Function function) {
        if(!this.targetInfoCache.containsKey(clazz)) {
            this.targetInfoCache.put(clazz, new TargetInfo<>(clazz, annotationClass, function));
        }
        return this.targetInfoCache.get(clazz);
    }

    public  T queryOne(String sql,
                                                       Class clazz,
                                                       Class annotationClass,
                                                       Function function) throws Exception {
        return queryOne(sql, this.getTarget(clazz, annotationClass, function));
    }

    private  Function getTarget(Class clazz,
                                                                       Class annotationClass,
                                                                       Function function) {
        this.cacheTarget(clazz, annotationClass, function);
        return resultSet -> this.fillFieldValue(clazz, resultSet);
    }

    public  List queryList(String sql, Class clazz) throws Exception {
        return queryList(sql, clazz, null, null);
    }

    public  T queryOne(String sql, Class clazz) throws Exception {
        return queryOne(sql, clazz, null, null);
    }

    public  T fillFieldValue(Class clazz, ResultSet resultSet) {
        try {
            T target = clazz.newInstance();
            TargetInfo targetInfo = this.targetInfoCache.get(clazz);
            for (TargetInfo.TargetFieldInfo targetFieldInfo : targetInfo.targetFieldInfoList) {
                Object object = getObject(resultSet, targetFieldInfo);
                if(nonNull(object)) {
                    boolean accessible = targetFieldInfo.field.isAccessible();
                    targetFieldInfo.field.setAccessible(true);
                    targetFieldInfo.field.set(target, object);
                    targetFieldInfo.field.setAccessible(accessible);
                }
            }
            return target;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private Object getObject(ResultSet resultSet, TargetInfo.TargetFieldInfo targetFieldInfo) throws SQLException {
        String fieldTypeName = targetFieldInfo.fieldType.getName();
        String columnLabel = targetFieldInfo.columnLabel;

        if(isNull(columnLabel)) {
            return null;
        }

        Object object;
        switch (fieldTypeName) {
            case "java.util.Date" :
                object = resultSet.getTimestamp(targetFieldInfo.columnLabel);
                break;
            case "java.lang.Byte" :
                object = resultSet.getByte(targetFieldInfo.columnLabel);
                break;
            case "java.time.LocalDateTime" :
                object = Optional.ofNullable(resultSet.getTimestamp(columnLabel))
                        .map(timestamp -> timestamp.toInstant()
                                .atZone( ZoneId.systemDefault() )
                                .toLocalDateTime())
                        .orElse(null);
                break;
            default:
                object = resultSet.getObject(columnLabel, targetFieldInfo.fieldType);
        }
        return object;
    }

    private static class TargetInfo {
        Class clazz;
        List targetFieldInfoList;

        public TargetInfo(Class clazz, Class annotationClass, Function function) {
            this.clazz = clazz;
            this.targetFieldInfoList = new ArrayList<>();
            Field[] declaredFields = FieldUtils.getAllFields(clazz);
            for (Field declaredField : declaredFields) {
                this.addTargetFieldInfo(declaredField, annotationClass, function);
            }
        }

        public TargetInfo addTargetFieldInfo(Field field, Class clazz, Function function) {
            TargetFieldInfo fieldInfo;
            if(isNull(clazz) || isNull(function)) {
                fieldInfo = new TargetFieldInfo<>(field, Column.class, Column::name);
            } else {
                fieldInfo = new TargetFieldInfo<>(field, clazz, function);
            }
            fieldInfo.fillColumnLabel(field, DataColumn.class, DataColumn::value);
            fieldInfo.fillColumnLabel(field, DataTable.class, DataTable::value);

            fieldInfo.fillColumnLabel(field, Table.class, Table::name);
            fieldInfo.fillColumnLabel(field, Column.class, Column::name);

            fieldInfo.fillColumnLabel(field, TableId.class, TableId::value);
            fieldInfo.fillColumnLabel(field, TableField.class, TableField::value);

            fieldInfo.fillColumnLabel(field, DataColumn.class, DataColumn::value);
            fieldInfo.fillColumnLabel(field, DataColumn.class, DataColumn::value);

            this.targetFieldInfoList.add(fieldInfo);
            return this;
        }

        private static class TargetFieldInfo {
            private Field field;
            private Class fieldType;
            private String columnLabel;

            public TargetFieldInfo(Field field, Class annotationClass, Function function) {
                this.field = field;
                this.fieldType = field.getType();
                this.fillColumnLabel(field, annotationClass, function);
            }

            private  void fillColumnLabel(Field field,
                                         Class annotationClass,
                                         Function function) {
                if(nonNull(this.columnLabel)
                        || isNull(field.getAnnotations())
                        || field.getAnnotations().length == 0) {
                    return;
                } else {
                    Annotation[] annotations = field.getAnnotations();
                    Map, Annotation> annotationMap = Arrays.stream(annotations)
                            .collect(Collectors.toMap(Annotation::annotationType, Function.identity()));

                    if (annotationMap.containsKey(annotationClass)) {
                        A annotation = (A) annotationMap.get(annotationClass);
                        this.columnLabel = function.apply(annotation);
                    }
                }
            }
        }
    }


    public  List queryList(String sql, Function function) throws Exception {
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery(sql);

        List dataList = new ArrayList<>();
        while (rs.next()) {
            T data = function.apply(rs);
            dataList.add(data);
        }
        rs.close();
        statement.close();
        return dataList;
    }



    public  T queryOne(String sql, Function function) throws Exception {
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery(sql);

        try {
            rs.next();
            return function.apply(rs);
        } finally {
            rs.close();
            statement.close();
            connection.close();
        }
    }

    public void closeConnection() {
        try {
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    private DataSourceTool() {
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy