zl程序教程

您现在的位置是:首页 >  后端

当前栏目

JAVA Postgresql 根据model类自动生成插入语句,批量插入数据

JAVA批量postgresql自动数据 生成 语句 插入
2023-09-27 14:26:27 时间

JAVA Postgresql 根据model类自动生成插入语句,批量插入数据

  1. 所有的类可以继承自一个BaseObject类(非必需);
  2. 数据库表中的字段名及类型必须与Object类中的一一对应;
  3. 调用通用的方法(对数据进行批量插入);

String.format(“insert into %s(%s) values(%s)”, tableName, fieldNames, marks);

主要涉及到应用反射,获取model类的所有字段名;
拼接sql中的字段名,及占位符;
然后再次利用反射对每一个字段设置值。

源码

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;

import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.StringJoiner;


/*************************************
 * Class Name: CommonDao
 * Description:〈通用数据Dao〉
 * @author Seminar
 * @Date 2023.01.18
 ************************************/
@Slf4j
public class CommonDao {
    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * 根据字段数组拼接问号
     *
     * @param fields 字段数组
     * @return
     */
    protected String getQueryMark(String fields) {
        String[] arr = fields.split(",");
        int len = arr.length;
        StringJoiner joiner = new StringJoiner(",");
        while (len-- > 0) {
            joiner.add("?");
        }
        return joiner.toString();
    }

    /**
     * 获取表记录总数
     *
     * @param tableName 表名
     * @return 记录总数
     */
    public Integer getTotal(String tableName) {
        return getTotal(tableName, null);
    }

    /**
     * 根据条件获取表记录总数
     *
     * @param tableName 表名
     * @param whereSql  关键字
     * @return 记录总数
     */
    public Integer getTotal(String tableName, String whereSql) {
        String sql = String.format("select count(*) as total from %s", tableName);
        if (!StringUtils.isEmpty(whereSql)) {
            sql += " where " + whereSql;
        }
        return jdbcTemplate.queryForObject(sql, Integer.class);
    }

    /**
     * 判断查询结果集中是否存在某列
     *
     * @param rs         查询结果集
     * @param columnName 列名
     * @return true 存在; false 不存咋
     */
    public boolean isExistColumn(ResultSet rs, String columnName) {
        try {
            if (rs.findColumn(columnName) > 0) {
                return true;
            }
        } catch (SQLException e) {
            return false;
        }
        return false;
    }

    /**
     * 根据字段名获取按?拼接的字符串
     *
     * @param fields 字段名,每一个占位一个?,特殊的集合类型,特殊处理
     * @return
     */
    protected String getQueryMark2(String fields) {
        String[] fieldNames = fields.split(",");
        String delimeter = ",";
        StringBuilder sb = new StringBuilder();
        for (String field : fieldNames) {
            if ("geometry".equals(field) || "s_index".equals(field)) {
                sb.append("ST_GeomFromText(?)" + delimeter);
            } else {
                sb.append("?" + delimeter);
            }
        }

        return sb.substring(0, sb.length() - 1);
    }

    /**
     * 批量插入通用方法(注意需要Object类中所有字段名与数据库中表列名的一致)
     *
     * @param objs      对象lists
     * @param tableName 插入的表名
     * @param <T>       通用BaseObject类
     */
    public <T> void batchInsertRdClassT(List<T> objs, String tableName) {
        if (objs == null || objs.isEmpty()) {
            return;
        }
        String fieldNames = getFieldNames(objs.get(0).getClass());
        String marks = getQueryMark2(fieldNames);
        String sql = String.format("insert into %s(%s) values(%s)", tableName, fieldNames, marks);
        log.info("{}", sql);
        int[] res = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                T item = objs.get(i);
                Field[] fieldVals = item.getClass().getDeclaredFields();
                for (int j = 0; j < fieldVals.length; j++) {
                    Field field = fieldVals[j];
                    field.setAccessible(true);

                    try {
                        setValue(ps, j + 1, field.get(item));
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

            @Override
            public int getBatchSize() {
                return objs.size();
            }
        });
    }

    /**
     * 对每一个字段设置值
     *
     * @param ps
     * @param index
     * @param column
     * @throws SQLException
     */
    private void setValue(PreparedStatement ps, int index, Object column) throws SQLException {
        if (column == null) {
            ps.setNull(index, 0);
        } else {
            if (column instanceof Long) {
                ps.setLong(index, (Long) column);
            } else if (column instanceof String) {
                ps.setLong(index, (Long) column);
            } else if (column instanceof Integer) {
                ps.setInt(index, (Integer) column);
            } else if (column instanceof Double) {
                ps.setDouble(index, (Double) column);
            } else if (column instanceof Boolean) {
                ps.setBoolean(index, (Boolean) column);
            }
        }
    }

    /**
     * 获取类的所有字段名,并,拼接
     *
     * @param clazz 实体类名
     * @return
     */
    private static String getFieldNames(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        String[] fieldNames = new String[fields.length];
        for (int i = 0; i < fields.length; i++) {
            fieldNames[i] = fields[i].getName();
        }
        return StringUtils.join(fieldNames, ",");
    }
}