123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- package com.primeton.dsp.dataservice.utils;
- import lombok.NonNull;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.dbcp2.BasicDataSource;
- import org.apache.commons.dbutils.DbUtils;
- import org.apache.commons.dbutils.QueryRunner;
- import org.apache.commons.dbutils.handlers.MapListHandler;
- import org.apache.commons.io.IOUtils;
- import org.apache.commons.lang.StringUtils;
- import javax.sql.DataSource;
- import java.io.Closeable;
- import java.io.IOException;
- import java.sql.*;
- import java.sql.Date;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.*;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- /**
- *
- * 数据库执行类。主要封装了查询,更新,批量更新等一些执行SQL的方法。
- *
- * <pre>
- *
- * Created by zhaopx.
- * User: zhaopx
- * Date: 2020-03-26
- * Time: 10:20
- *
- * </pre>
- *
- * @author zhaopx
- */
- @Slf4j
- public class SQLRunner implements Closeable {
- protected final DataSource ds;
- public SQLRunner(Properties config) {
- this(config.getProperty("jdbc.driverClassName"),
- config.getProperty("jdbc.url"),
- config.getProperty("jdbc.user"),
- config.getProperty("jdbc.password"));
- }
- public SQLRunner(String driverClass,
- String url,
- String user,
- String password) {
- BasicDataSource dataSource = new BasicDataSource();
- dataSource.setMaxTotal(2);
- dataSource.setMinIdle(1);
- dataSource.setInitialSize(1);
- dataSource.setDriverClassName(driverClass);
- dataSource.setUrl(url);
- dataSource.setUsername(user);
- dataSource.setPassword(password);
- this.ds = dataSource;
- }
- public SQLRunner(@NonNull DataSource ds) {
- this.ds = ds;
- }
- public int update(String sql) throws SQLException {
- if(sql == null) {
- throw new SQLException("Null SQL statement");
- }
- Connection conn = ds.getConnection();
- if(conn == null) {
- throw new SQLException("Null connection");
- }
- Statement statement = null;
- int r = 0;
- try {
- statement = conn.createStatement();
- r = statement.executeUpdate(sql);
- } finally {
- close(conn, statement, null);
- }
- return r;
- }
- public int update(String sql, Object[] params) throws SQLException {
- QueryRunner runner = new QueryRunner(this.ds);
- return runner.update(sql, params);
- }
- /**
- * 批量更新
- * @param sql SQL 值 ? 代替
- * @param params 参数数组
- * @return
- * @throws SQLException
- */
- public int[] updateBatch(String sql, List<Object[]> params) throws SQLException {
- QueryRunner runner = new QueryRunner(this.ds);
- return runner.batch(sql, params.toArray(new Object[params.size()][]));
- }
- /**
- * 查询 sql,带参数
- * @param sql
- * @param params
- * @return
- * @throws SQLException
- */
- public QueryResult query(String sql, Object[] params) throws SQLException {
- if(params.length == 0) {
- // 不带参数的查询
- return query(sql);
- }
- // 没有参数,QueryRunner 会报错
- QueryRunner runner = new QueryRunner(this.ds);
- RSTypeHandler typeHandler = new RSTypeHandler();
- List<Map<String, Object>> list = runner.query(sql, typeHandler, params);
- QueryResult queryResult = new QueryResult(typeHandler.getTypes(), list);
- queryResult.setSql(sql);
- return queryResult;
- }
- /**
- * 无参数的查询
- * @param sql
- * @return
- * @throws SQLException
- */
- public QueryResult query(String sql) throws SQLException {
- Connection conn = ds.getConnection();
- if(conn == null) {
- throw new SQLException("Null connection");
- } else if(sql == null) {
- DbUtils.close(conn);
- throw new SQLException("Null SQL statement");
- } else {
- Statement statement = null;
- ResultSet rs = null;
- try {
- statement = conn.createStatement();
- rs = statement.executeQuery(sql);
- RSTypeHandler typeHandler = new RSTypeHandler();
- List<Map<String, Object>> list = typeHandler.handle(rs);
- QueryResult queryResult = new QueryResult(typeHandler.getTypes(), list);
- queryResult.setSql(sql);
- return queryResult;
- } catch (SQLException e) {
- // 没有返回值
- if(e.getMessage().contains("not generate a result set")) {
- log.warn("execute sql: '"+sql+"' success, no result set.", e);
- QueryResult queryResult = new QueryResult(Collections.<Map<String, Object>>emptyList(), Collections.<Map<String, Object>>emptyList());
- queryResult.setSql(sql);
- return queryResult;
- }
- throw e;
- } finally {
- close(conn, statement, rs);
- }
- }
- }
- /**
- * 查询 sql,带参数
- * @param sql
- * @param params
- * @return
- * @throws SQLException
- */
- public QueryResult queryOne(String sql, Object[] params) throws SQLException {
- if(params.length == 0) {
- // 不带参数的查询
- return query(sql);
- }
- // 没有参数,QueryRunner 会报错
- QueryRunner runner = new QueryRunner(this.ds);
- RSTypeHandler typeHandler = new RSTypeHandler();
- List<Map<String, Object>> list = runner.query(sql, typeHandler, params);
- QueryResult queryResult = new QueryResult(typeHandler.getTypes(), list);
- queryResult.setSql(sql);
- return queryResult;
- }
- @Override
- public void close() throws IOException {
- try {
- ((BasicDataSource)ds).close();
- } catch (SQLException e) {
- }
- }
- /**
- * 安静的关闭数据库链接。
- *
- * @param conn
- * @param ps
- * @param rs
- */
- public static void close(Connection conn, Statement ps, ResultSet rs) {
- try {
- if (rs != null) {
- rs.close();
- }
- } catch (Exception e) { }
- try {
- if (ps != null) {
- ps.close();
- }
- } catch (Exception e) {}
- try {
- if (conn != null) {
- conn.close();
- }
- } catch (Exception e) {}
- }
- /**
- * 根据 SQL 的 ${field} 按照 map 中的参数替换,组成一个新的 SQL 返回。
- * @param sql 支持 ${field} 的变量替换
- * @param params 参数,如果没有参数则会原路返回
- * @return 返回新的变量替换的 SQL
- */
- public static String getMatchSQL(String sql, Map<String, Object> params){
- Matcher matcher = Pattern.compile("(\\$\\{\\w+\\})").matcher(sql);
- StringBuffer sb = new StringBuffer();
- while (matcher.find()) {
- String group = matcher.group();
- String field = StringUtils.trim(group.substring(2, group.length() - 1));
- String val = (String)params.get(field);
- if(val == null) {
- continue;
- }
- matcher.appendReplacement(sb, val);
- }
- matcher.appendTail(sb);
- return sb.toString();
- }
- /**
- * 获取一个 sql 内 from table 的table 名称,如果是join sql 则获取多个from的表名
- * @param sql
- * @return
- */
- public static String[] getSQLTable(String sql) {
- //select sql 里 from 后的字符和join后的字符,都是表名
- //正则表达式,不区分大小写的模式
- Pattern compile = Pattern.compile("(TABLE|JOIN|FROM){1}\\s+(\\w+)", Pattern.CASE_INSENSITIVE);
- Matcher matcher = compile.matcher(sql);
- List<String> names = new ArrayList<>(3);
- while (matcher.find()) {
- String name = matcher.group(2);
- names.add(name);
- }
- return names.toArray(new String[names.size()]);
- }
- /**
- *
- * 把值 val 转为 type 的类型, type 为数据库的类型
- *
- * @param val 字段值
- * @param type 字段类型
- * @return
- */
- public static Object convertVal(Object val, String type) {
- if(val == null) {
- return null;
- }
- type = type.toUpperCase();
- switch (type){
- case "VARCHAR":
- case "VARCHAR2":
- case "TEXT":
- case "BLOB":
- return val instanceof String ? (String)val : String.valueOf(val);
- case "TINYINT":
- case "SMALLINT":
- case "INT":
- return val instanceof Number ? ((Number)val).intValue() : Integer.parseInt(String.valueOf(val));
- case "DECIMAL":
- case "FLOAT":
- return val instanceof Number ? ((Number)val).floatValue() : Float.parseFloat(String.valueOf(val));
- case "DOUBLE":
- return val instanceof Number ? ((Number)val).doubleValue() : Float.parseFloat(String.valueOf(val));
- case "BIGINT":
- return val instanceof Number ? ((Number)val).longValue() : Long.parseLong(String.valueOf(val));
- case "DATETIME":
- if(val instanceof java.util.Date){
- return new Timestamp(((java.util.Date)val).getTime());
- } else if(val instanceof Number) {
- return new Timestamp(((Number) val).longValue());
- }
- try {
- return new Timestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(val.toString()).getTime());
- } catch (ParseException e) {
- throw new IllegalArgumentException(e);
- }
- case "DATE":
- if(val instanceof java.util.Date){
- return new Date(((java.util.Date)val).getTime());
- } else if(val instanceof Number) {
- return new Date(((Number) val).longValue());
- }
- try {
- return new Date(new SimpleDateFormat("yyyy-MM-dd").parse(val.toString()).getTime());
- } catch (ParseException e) {
- throw new IllegalArgumentException(e);
- }
- case "TIME":
- if(val instanceof java.util.Date){
- return new Time(((java.util.Date)val).getTime());
- } else if(val instanceof Number) {
- return new Time(((Number) val).longValue());
- }
- try {
- return new Time(new SimpleDateFormat("HH:mm:ss").parse(val.toString()).getTime());
- } catch (ParseException e) {
- throw new IllegalArgumentException(e);
- }
- default:
- return val instanceof String ? (String)val : String.valueOf(val);
- }
- }
- }
|