diff --git a/datagear-analysis/src/main/java/org/datagear/analysis/support/SqlDataSet.java b/datagear-analysis/src/main/java/org/datagear/analysis/support/SqlDataSet.java index 4a343f5e..24f963a9 100644 --- a/datagear-analysis/src/main/java/org/datagear/analysis/support/SqlDataSet.java +++ b/datagear-analysis/src/main/java/org/datagear/analysis/support/SqlDataSet.java @@ -21,7 +21,7 @@ import org.datagear.analysis.DataSetProperty; import org.datagear.analysis.DataSetResult; import org.datagear.analysis.support.ParameterSqlResolver.ParameterSql; import org.datagear.util.JdbcUtil; -import org.datagear.util.JdbcUtil.QueryResultSet; +import org.datagear.util.QueryResultSet; import org.datagear.util.resource.ConnectionFactory; /** @@ -125,7 +125,7 @@ public class SqlDataSet extends AbstractDataSet if (!paramNames.isEmpty()) { - HashMap myParamValues = new HashMap(); + HashMap myParamValues = new HashMap<>(); if (paramValues != null) myParamValues.putAll(paramValues); diff --git a/datagear-analysis/src/main/java/org/datagear/analysis/support/SqlDataSetSupport.java b/datagear-analysis/src/main/java/org/datagear/analysis/support/SqlDataSetSupport.java index d3f6975e..82494d97 100644 --- a/datagear-analysis/src/main/java/org/datagear/analysis/support/SqlDataSetSupport.java +++ b/datagear-analysis/src/main/java/org/datagear/analysis/support/SqlDataSetSupport.java @@ -26,8 +26,9 @@ import org.datagear.analysis.DataSetParam; import org.datagear.analysis.DataSetProperty; import org.datagear.analysis.DataType; import org.datagear.analysis.support.ParameterSqlResolver.ParameterSql; +import org.datagear.util.JdbcSupport; import org.datagear.util.JdbcUtil; -import org.datagear.util.JdbcUtil.QueryResultSet; +import org.datagear.util.QueryResultSet; import org.datagear.util.StringUtil; /** @@ -36,7 +37,7 @@ import org.datagear.util.StringUtil; * @author datagear@163.com * */ -public class SqlDataSetSupport +public class SqlDataSetSupport extends JdbcSupport { protected static final ParameterSqlResolver PARAMETER_SQL_RESOLVER = new ParameterSqlResolver(); @@ -67,13 +68,12 @@ public class SqlDataSetSupport { if (dataSetParams == null || dataSetParams.isEmpty()) { - st = cn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + st = createQueryStatement(cn, ResultSet.TYPE_FORWARD_ONLY); rs = st.executeQuery(sql); } else { - PreparedStatement pst = cn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_READ_ONLY); + PreparedStatement pst = createQueryPreparedStatement(cn, sql, ResultSet.TYPE_FORWARD_ONLY); setPreparedStatementParams(pst, dataSetParams, paramValues); st = pst; @@ -249,14 +249,14 @@ public class SqlDataSetSupport public List> resolveDatas(Connection cn, ResultSet rs, List properties) throws SQLException { - List> datas = new ArrayList>(); + List> datas = new ArrayList<>(); ResultSetMetaData rsMeta = rs.getMetaData(); int[] rsColumns = resolveResultsetColumns(properties, rsMeta); while (rs.next()) { - Map row = new HashMap(); + Map row = new HashMap<>(); for (int i = 0; i < rsColumns.length; i++) { @@ -522,7 +522,7 @@ public class SqlDataSetSupport ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); - List properties = new ArrayList(columnCount); + List properties = new ArrayList<>(columnCount); for (int i = 1; i <= columnCount; i++) { @@ -619,7 +619,7 @@ public class SqlDataSetSupport return dataType; } - + /** * 解析SQL语句参数名列表。 * diff --git a/datagear-dataexchange/src/main/java/org/datagear/dataexchange/AbstractDevotedDataExchangeService.java b/datagear-dataexchange/src/main/java/org/datagear/dataexchange/AbstractDevotedDataExchangeService.java index 1dadbbe9..3435344d 100644 --- a/datagear-dataexchange/src/main/java/org/datagear/dataexchange/AbstractDevotedDataExchangeService.java +++ b/datagear-dataexchange/src/main/java/org/datagear/dataexchange/AbstractDevotedDataExchangeService.java @@ -192,11 +192,11 @@ public abstract class AbstractDevotedDataExchangeService Connection cn = getConnection(context); if (ExceptionResolve.ABORT.equals(exceptionResolve) || ExceptionResolve.IGNORE.equals(exceptionResolve)) - commitSilently(cn); + JdbcUtil.commitSilently(cn); else if (ExceptionResolve.ROLLBACK.equals(exceptionResolve)) - rollbackSilently(cn); + JdbcUtil.rollbackSilently(cn); else - rollbackSilently(cn); + JdbcUtil.rollbackSilently(cn); } protected Connection getConnection(DataExchangeContext context) throws DataExchangeException diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/Dialect.java b/datagear-persistence/src/main/java/org/datagear/persistence/Dialect.java index a29f4e50..99eae3b8 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/Dialect.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/Dialect.java @@ -7,6 +7,7 @@ package org.datagear.persistence; import java.sql.ResultSet; import org.datagear.meta.Table; +import org.datagear.util.Sql; /** * 数据库方言。 diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/PagingQuery.java b/datagear-persistence/src/main/java/org/datagear/persistence/PagingQuery.java index 0a4092b6..67438944 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/PagingQuery.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/PagingQuery.java @@ -24,6 +24,19 @@ public class PagingQuery extends Query super(); } + public PagingQuery(int page) + { + super(); + this.paging.setPage(page); + } + + public PagingQuery(int page, int pageSize) + { + super(); + this.paging.setPage(page); + this.paging.setPageSize(pageSize); + } + public PagingQuery(int page, int pageSize, String keyword) { super(keyword); diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/support/AbstractDialect.java b/datagear-persistence/src/main/java/org/datagear/persistence/support/AbstractDialect.java index 97630222..69999f49 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/support/AbstractDialect.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/support/AbstractDialect.java @@ -10,8 +10,8 @@ import org.datagear.meta.Table; import org.datagear.persistence.Dialect; import org.datagear.persistence.Order; import org.datagear.persistence.Query; -import org.datagear.persistence.Sql; import org.datagear.util.JdbcUtil; +import org.datagear.util.Sql; /** * 抽象{@linkplain Dialect}。 diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/support/DefaultDialectSource.java b/datagear-persistence/src/main/java/org/datagear/persistence/support/DefaultDialectSource.java index f687bcbb..d043f01d 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/support/DefaultDialectSource.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/support/DefaultDialectSource.java @@ -6,6 +6,7 @@ package org.datagear.persistence.support; import java.sql.Connection; import java.sql.DatabaseMetaData; +import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -21,11 +22,11 @@ import org.datagear.persistence.DialectBuilder; import org.datagear.persistence.DialectException; import org.datagear.persistence.DialectSource; import org.datagear.persistence.Order; -import org.datagear.persistence.Sql; import org.datagear.persistence.support.dialect.MysqlDialectBuilder; import org.datagear.persistence.support.dialect.OracleDialectBuilder; import org.datagear.persistence.support.dialect.SqlServerDialectBuilder; import org.datagear.util.JdbcUtil; +import org.datagear.util.Sql; /** * 默认{@linkplain DialectSource}。 @@ -41,7 +42,7 @@ public class DefaultDialectSource extends PersistenceSupport implements DialectS private boolean detection = true; - private ConcurrentMap dialectBuilderCache = new ConcurrentHashMap(); + private ConcurrentMap dialectBuilderCache = new ConcurrentHashMap<>(); public DefaultDialectSource() { @@ -52,7 +53,7 @@ public class DefaultDialectSource extends PersistenceSupport implements DialectS { super(); this.dbMetaResolver = dbMetaResolver; - this.dialectBuilders = new ArrayList(); + this.dialectBuilders = new ArrayList<>(); this.dialectBuilders.add(new MysqlDialectBuilder()); this.dialectBuilders.add(new OracleDialectBuilder()); @@ -240,7 +241,7 @@ public class DefaultDialectSource extends PersistenceSupport implements DialectS Sql pagingQuerySql = dialect.toPagingQuerySql(query, orders, 1, 5); - executeQuery(cn, pagingQuerySql); + executeQuery(cn, pagingQuerySql, ResultSet.TYPE_FORWARD_ONLY); return true; } diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/support/DefaultPersistenceManager.java b/datagear-persistence/src/main/java/org/datagear/persistence/support/DefaultPersistenceManager.java index df59b12c..6e9fc949 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/support/DefaultPersistenceManager.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/support/DefaultPersistenceManager.java @@ -6,6 +6,7 @@ package org.datagear.persistence.support; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; @@ -23,8 +24,8 @@ import org.datagear.persistence.PstValueMapper; import org.datagear.persistence.Query; import org.datagear.persistence.Row; import org.datagear.persistence.RowMapper; -import org.datagear.persistence.Sql; import org.datagear.util.JdbcUtil; +import org.datagear.util.Sql; import org.datagear.util.StringUtil; /** @@ -102,7 +103,7 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per valueSql.sql(")"); sql.sql(valueSql); - return executeUpdate(cn, sql); + return executeUpdateWrap(cn, sql); } @Override @@ -138,7 +139,7 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per sql.sql(" WHERE ").sql(buildUniqueRecordCondition(cn, dialect, table, origin, mapper)); - return executeUpdate(cn, sql); + return executeUpdateWrap(cn, sql); } @Override @@ -177,7 +178,7 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per try { - pst = createPreparedStatement(cn, sql); + pst = createUpdatePreparedStatement(cn, sql.getSqlValue()); int count = 0; @@ -255,7 +256,7 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per sql.sqld(quote(dialect, name) + "=?").param(value, column.getType()); } - List rows = executeListQuery(cn, table, sql, rowMapper); + List rows = executeListQuery(cn, table, sql, ResultSet.TYPE_FORWARD_ONLY, rowMapper); if (rows.size() > 1) throw new NonUniqueResultException(); @@ -276,12 +277,11 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per dialect = getDialect(cn, dialect); Sql sql = buildQuery(cn, dialect, table, query); - return executeListQuery(cn, table, sql, mapper); + return executeListQuery(cn, table, sql, ResultSet.TYPE_FORWARD_ONLY, mapper); } @Override - public PagingData pagingQuery(Connection cn, Table table, PagingQuery pagingQuery) - throws PersistenceException + public PagingData pagingQuery(Connection cn, Table table, PagingQuery pagingQuery) throws PersistenceException { return pagingQuery(cn, null, table, pagingQuery, null); } @@ -294,20 +294,20 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per Sql queryView = buildQuery(cn, dialect, table, pagingQuery); - long total = executeCountQuery(cn, queryView); + long total = queryCount(cn, queryView); PagingData pagingData = new PagingData<>(pagingQuery.getPage(), total, pagingQuery.getPageSize()); Sql query = null; - + List rows = null; int startRow = pagingData.getStartRow(); int count = pagingData.getPageSize(); - // 数据库分页 if (dialect.supportsPagingSql()) { query = dialect.toPagingQuerySql(queryView, pagingQuery.getOrders(), startRow, count); + // 数据库分页 if (query != null) { startRow = 1; @@ -319,7 +319,7 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per if (query == null) query = dialect.toOrderSql(queryView, pagingQuery.getOrders()); - List rows = executeListQuery(cn, table, query, startRow, count, mapper); + rows = executeListQuery(cn, table, query, ResultSet.TYPE_SCROLL_INSENSITIVE, startRow, count, mapper); pagingData.setItems(rows); @@ -330,7 +330,7 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per { Sql countQuery = Sql.valueOf().sql("SELECT COUNT(*) FROM (").sql(query).sql(") T"); - long re = executeCountQuery(cn, countQuery); + long re = executeCountQueryWrap(cn, countQuery); return re; } @@ -398,13 +398,13 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per * @param dialect * @param table * @param row - * @param mapper 允许为{@code null} + * @param mapper + * 允许为{@code null} * @return * @throws PersistenceException */ protected Sql buildUniqueRecordCondition(Connection cn, Dialect dialect, Table table, Row row, - PstValueMapper mapper) - throws PersistenceException + PstValueMapper mapper) throws PersistenceException { Column[] columns = getUniqueRecordColumns(table); @@ -484,13 +484,13 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per * @param table * @param column * @param value - * @param mapper 允许为{@code null} + * @param mapper + * 允许为{@code null} * @return * @throws PersistenceException */ - protected Object mapToPstValue(Connection cn, Dialect dialect, Table table, Column column, - Object value, PstValueMapper mapper) - throws PersistenceException + protected Object mapToPstValue(Connection cn, Dialect dialect, Table table, Column column, Object value, + PstValueMapper mapper) throws PersistenceException { if (mapper == null) return value; @@ -501,7 +501,8 @@ public class DefaultPersistenceManager extends PersistenceSupport implements Per /** * * @param cn - * @param init 允许为{@code null} + * @param init + * 允许为{@code null} * @return * @throws PersistenceException */ diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/support/PersistenceSupport.java b/datagear-persistence/src/main/java/org/datagear/persistence/support/PersistenceSupport.java index c738b8ef..a70fcd0c 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/support/PersistenceSupport.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/support/PersistenceSupport.java @@ -4,22 +4,9 @@ package org.datagear.persistence.support; -import java.io.Closeable; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Blob; -import java.sql.Clob; import java.sql.Connection; -import java.sql.NClob; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.SQLXML; -import java.sql.Types; import java.util.ArrayList; import java.util.List; @@ -30,13 +17,9 @@ import org.datagear.persistence.PersistenceException; import org.datagear.persistence.Row; import org.datagear.persistence.RowMapper; import org.datagear.persistence.RowMapperException; -import org.datagear.persistence.Sql; -import org.datagear.persistence.SqlParamValue; -import org.datagear.util.IOUtil; -import org.datagear.util.JDBCCompatiblity; -import org.datagear.util.JdbcUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.datagear.util.JdbcSupport; +import org.datagear.util.QueryResultSet; +import org.datagear.util.Sql; /** * 持久操作支持类。 @@ -44,10 +27,8 @@ import org.slf4j.LoggerFactory; * @author datagear@163.com * */ -public class PersistenceSupport +public class PersistenceSupport extends JdbcSupport { - private static final Logger LOGGER = LoggerFactory.getLogger(PersistenceSupport.class); - /** * 转换为引号名字。 * @@ -61,17 +42,43 @@ public class PersistenceSupport } /** - * 执行列表结果查询。 + * 执行数目查询。 * * @param cn - * @param table * @param sql * @return * @throws PersistenceException */ - public List executeListQuery(Connection cn, Table table, Sql sql) throws PersistenceException + public long executeCountQueryWrap(Connection cn, Sql sql) throws PersistenceException { - return executeListQuery(cn, table, sql, 1, -1, null); + try + { + return executeCountQuery(cn, sql); + } + catch (SQLException e) + { + throw new PersistenceException(e); + } + } + + /** + * 执行更新。 + * + * @param cn + * @param sql + * @return + * @throws PersistenceException + */ + public int executeUpdateWrap(Connection cn, Sql sql) throws PersistenceException + { + try + { + return executeUpdate(cn, sql); + } + catch (SQLException e) + { + throw new PersistenceException(e); + } } /** @@ -80,21 +87,41 @@ public class PersistenceSupport * @param cn * @param table * @param sql + * @param resultSetType + * @return + * @throws PersistenceException + */ + public List executeListQuery(Connection cn, Table table, Sql sql, int resultSetType) + throws PersistenceException + { + return executeListQuery(cn, table, sql, resultSetType, 1, -1, null); + } + + /** + * 执行列表结果查询。 + * + * @param cn + * @param table + * @param sql + * @param resultSetType * @param mapper * 允许为{@code null} * @return * @throws PersistenceException */ - public List executeListQuery(Connection cn, Table table, Sql sql, RowMapper mapper) throws PersistenceException + public List executeListQuery(Connection cn, Table table, Sql sql, int resultSetType, RowMapper mapper) + throws PersistenceException { - return executeListQuery(cn, table, sql, 1, -1, mapper); + return executeListQuery(cn, table, sql, resultSetType, 1, -1, mapper); } /** * 执行列表结果查询。 * * @param cn - * @param query + * @param table + * @param sql + * @param resultSetType * @param startRow * 起始行号,以{@code 1}开头 * @param count @@ -103,8 +130,8 @@ public class PersistenceSupport * 允许为{@code null} * @return */ - public List executeListQuery(Connection cn, Table table, Sql sql, int startRow, int count, RowMapper mapper) - throws PersistenceException + public List executeListQuery(Connection cn, Table table, Sql sql, int resultSetType, int startRow, int count, + RowMapper mapper) throws PersistenceException { if (startRow < 1) startRow = 1; @@ -115,12 +142,12 @@ public class PersistenceSupport try { - qrs = executeQuery(cn, sql); + qrs = executeQuery(cn, sql, resultSetType); ResultSet rs = qrs.getResultSet(); if (count >= 0 && startRow > 1) - JdbcUtil.moveToBeforeRow(rs, startRow); + forwardBefore(rs, startRow); int endRow = (count >= 0 ? startRow + count : -1); @@ -192,7 +219,7 @@ public class PersistenceSupport Column[] columns = table.getColumns(); for (int i = 0; i < columns.length; i++) { - Object value = getColumnValue(cn, rs, columns[i]); + Object value = getColumnValue(cn, rs, columns[i].getName(), columns[i].getType()); row.put(columns[i].getName(), value); } } @@ -205,718 +232,8 @@ public class PersistenceSupport } } - /** - * 执行数目查询。 - * - * @param cn - * @param query - * @return - */ - public long executeCountQuery(Connection cn, Sql query) - { - QueryResultSet qrs = null; - - try - { - long count = 0; - - qrs = executeQuery(cn, query); - - ResultSet rs = qrs.getResultSet(); - - if (rs.next()) - count = rs.getInt(1); - - return count; - } - catch (SQLException e) - { - throw new PersistenceException(e); - } - finally - { - QueryResultSet.close(qrs); - } - } - - public QueryResultSet executeQuery(Connection cn, Sql sql) throws PersistenceException - { - PreparedStatement pst = null; - ResultSet rs = null; - List setParams = null; - try - { - pst = createPreparedStatement(cn, sql); - setParams = setParamValues(cn, pst, sql); - rs = pst.executeQuery(); - - return new QueryResultSet(pst, rs, setParams); - } - catch (SQLException e) - { - closeIfClosable(setParams); - JdbcUtil.closeResultSet(rs); - JdbcUtil.closeStatement(pst); - - throw new PersistenceException(e); - } - } - - public int executeUpdate(Connection cn, Sql sql) throws PersistenceException - { - PreparedStatement pst = null; - List setParams = null; - - try - { - pst = createPreparedStatement(cn, sql); - setParams = setParamValues(cn, pst, sql); - - return pst.executeUpdate(); - } - catch (SQLException e) - { - throw new PersistenceException(e); - } - finally - { - closeIfClosable(setParams); - JdbcUtil.closeStatement(pst); - } - } - - public List setParamValues(Connection cn, PreparedStatement st, Sql sql) throws SQLException - { - return setParamValues(cn, st, sql.getParamValues()); - } - - public List setParamValues(Connection cn, PreparedStatement st, List paramValues) - throws SQLException - { - List setValues = new ArrayList<>(paramValues.size()); - - for (int i = 1; i <= paramValues.size(); i++) - { - Object setValue = setParamValue(cn, st, i, paramValues.get(i - 1)); - setValues.add(setValue); - } - - return setValues; - } - - public Object[] setParamValues(Connection cn, PreparedStatement st, SqlParamValue... paramValues) - throws SQLException - { - Object[] setValues = new Object[paramValues.length]; - - for (int i = 1; i <= paramValues.length; i++) - setValues[i - 1] = setParamValue(cn, st, i, paramValues[i - 1]); - - return setValues; - } - - public PreparedStatement createPreparedStatement(Connection cn, Sql sql) throws PersistenceException - { - PreparedStatement pst = null; - - try - { - pst = cn.prepareStatement(sql.getSqlValue()); - } - catch (SQLException e) - { - JdbcUtil.closeStatement(pst); - - throw new PersistenceException(e); - } - - return pst; - } - - /** - * 设置{@linkplain PreparedStatement}的参数值。 - *

- * 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Java Types Mapper to - * JDBC Types”表。 - *

- * - * @param cn - * @param st - * @param paramIndex - * @param paramValue - * @return - * @throws SQLException - */ - @JDBCCompatiblity("某些驱动程序不支持PreparedStatement.setObject方法(比如:Hive JDBC),所以这里没有使用") - public Object setParamValue(Connection cn, PreparedStatement st, int paramIndex, SqlParamValue paramValue) - throws SQLException - { - int sqlType = paramValue.getType(); - Object value = paramValue.getValue(); - - if (value == null) - { - st.setNull(paramIndex, sqlType); - return null; - } - - switch (sqlType) - { - case Types.CHAR: - case Types.VARCHAR: - case Types.LONGVARCHAR: - { - if (value instanceof String) - st.setString(paramIndex, (String) value); - else if (value instanceof Reader) - st.setCharacterStream(paramIndex, (Reader) value); - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.NUMERIC: - case Types.DECIMAL: - { - BigDecimal v = null; - - if (value instanceof BigDecimal) - v = (BigDecimal) value; - else if (value instanceof BigInteger) - v = new BigDecimal((BigInteger) value); - else if (value instanceof Number) - v = new BigDecimal(((Number) value).doubleValue()); - - if (v != null) - { - st.setBigDecimal(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.BIT: - case Types.BOOLEAN: - { - if (value instanceof Boolean) - st.setBoolean(paramIndex, (Boolean) value); - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.TINYINT: - case Types.SMALLINT: - case Types.INTEGER: - { - Integer v = null; - - if (value instanceof Integer) - v = (Integer) value; - else if (value instanceof Number) - v = ((Number) value).intValue(); - - if (v != null) - { - st.setInt(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.BIGINT: - { - Long v = null; - - if (value instanceof Long) - v = (Long) value; - else if (value instanceof Number) - v = ((Number) value).longValue(); - - if (v != null) - { - st.setLong(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.REAL: - { - Float v = null; - - if (value instanceof Float) - v = (Float) value; - else if (value instanceof Number) - v = ((Number) value).floatValue(); - - if (v != null) - { - st.setFloat(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.FLOAT: - case Types.DOUBLE: - { - Double v = null; - - if (value instanceof Double) - v = (Double) value; - else if (value instanceof Number) - v = ((Number) value).doubleValue(); - - if (v != null) - { - st.setDouble(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.BINARY: - case Types.VARBINARY: - case Types.LONGVARBINARY: - { - if (value instanceof byte[]) - st.setBytes(paramIndex, (byte[]) value); - else if (value instanceof InputStream) - st.setBinaryStream(paramIndex, (InputStream) value); - else if (value instanceof File) - { - InputStream v = getInputStreamForSql((File) value); - st.setBinaryStream(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.DATE: - { - java.sql.Date v = null; - - if (value instanceof java.sql.Date) - v = (java.sql.Date) value; - else if (value instanceof java.util.Date) - v = new java.sql.Date(((java.util.Date) value).getTime()); - - if (v != null) - { - st.setDate(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.TIME: - { - java.sql.Time v = null; - - if (value instanceof java.sql.Time) - v = (java.sql.Time) value; - else if (value instanceof java.util.Date) - v = new java.sql.Time(((java.util.Date) value).getTime()); - - if (v != null) - { - st.setTime(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.TIMESTAMP: - { - java.sql.Timestamp v = null; - - if (value instanceof java.sql.Timestamp) - v = (java.sql.Timestamp) value; - else if (value instanceof java.util.Date) - v = new java.sql.Timestamp(((java.util.Date) value).getTime()); - - if (v != null) - { - st.setTimestamp(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.CLOB: - { - if (value instanceof Clob) - st.setClob(paramIndex, (Clob) value); - else if (value instanceof Reader) - st.setClob(paramIndex, (Reader) value); - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.BLOB: - { - if (value instanceof Blob) - st.setBlob(paramIndex, (Blob) value); - else if (value instanceof InputStream) - st.setBlob(paramIndex, (InputStream) value); - else if (value instanceof File) - { - InputStream v = getInputStreamForSql((File) value); - st.setBlob(paramIndex, v); - value = v; - } - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.NCHAR: - case Types.NVARCHAR: - case Types.LONGNVARCHAR: - { - if (value instanceof String) - st.setNString(paramIndex, (String) value); - else if (value instanceof Reader) - st.setNCharacterStream(paramIndex, (Reader) value); - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.NCLOB: - { - if (value instanceof NClob) - st.setNClob(paramIndex, (NClob) value); - else if (value instanceof Reader) - st.setNClob(paramIndex, (Reader) value); - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - case Types.SQLXML: - { - if (value instanceof SQLXML) - st.setSQLXML(paramIndex, (SQLXML) value); - else - value = setParamValueExt(cn, st, paramIndex, paramValue); - - break; - } - - default: - value = setParamValueExt(cn, st, paramIndex, paramValue); - } - - return value; - } - - /** - * 扩展设置{@linkplain SqlParamValue}。 - * - * @param cn - * @param st - * @param paramIndex - * @param paramValue - * @return - * @throws SQLException - */ - protected Object setParamValueExt(Connection cn, PreparedStatement st, int paramIndex, SqlParamValue paramValue) - throws SQLException - { - throw new UnsupportedOperationException("Set JDBC [" + paramValue.getType() + "] type value is not supported"); - } - - protected InputStream getInputStreamForSql(File file) throws SQLException - { - try - { - return IOUtil.getInputStream(file); - } - catch (FileNotFoundException e) - { - throw new SQLException("File [" + file.getAbsolutePath() + "] not found"); - } - } - - /** - * 获取列值。 - *

- * 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Type Conversions - * Supported by ResultSet getter Methods”表,并且使用其中的最佳方法。 - *

- * - * @param cn - * @param rs - * @param column - * @return - * @throws SQLException - */ public Object getColumnValue(Connection cn, ResultSet rs, Column column) throws SQLException { - String columnName = column.getName(); - int sqlType = column.getType(); - - Object value = null; - - switch (sqlType) - { - case Types.TINYINT: - { - value = rs.getByte(columnName); - break; - } - - case Types.SMALLINT: - { - value = rs.getShort(columnName); - break; - } - - case Types.INTEGER: - { - value = rs.getInt(columnName); - break; - } - - case Types.BIGINT: - { - value = rs.getLong(columnName); - break; - } - - case Types.REAL: - { - value = rs.getFloat(columnName); - break; - } - - case Types.FLOAT: - case Types.DOUBLE: - { - value = rs.getDouble(columnName); - break; - } - - case Types.DECIMAL: - case Types.NUMERIC: - { - value = rs.getBigDecimal(columnName); - break; - } - - case Types.BIT: - { - value = rs.getBoolean(columnName); - break; - } - - case Types.BOOLEAN: - { - value = rs.getBoolean(columnName); - break; - } - - case Types.CHAR: - case Types.VARCHAR: - { - value = rs.getString(columnName); - break; - } - - case Types.LONGVARCHAR: - { - value = rs.getCharacterStream(columnName); - break; - } - - case Types.BINARY: - case Types.VARBINARY: - { - value = rs.getBytes(columnName); - break; - } - - case Types.LONGVARBINARY: - { - value = rs.getBinaryStream(columnName); - break; - } - - case Types.DATE: - { - value = rs.getDate(columnName); - break; - } - - case Types.TIME: - { - value = rs.getTime(columnName); - break; - } - - case Types.TIMESTAMP: - { - value = rs.getTimestamp(columnName); - break; - } - - case Types.CLOB: - { - value = rs.getClob(columnName); - break; - } - - case Types.BLOB: - { - value = rs.getBlob(columnName); - break; - } - - case Types.NCHAR: - case Types.NVARCHAR: - { - value = rs.getNString(columnName); - break; - } - - case Types.LONGNVARCHAR: - { - value = rs.getNCharacterStream(columnName); - break; - } - - case Types.NCLOB: - { - value = rs.getNClob(columnName); - break; - } - - case Types.SQLXML: - { - value = rs.getSQLXML(columnName); - break; - } - - default: - value = getColumnValueExt(cn, rs, column, columnName); - break; - } - - if (rs.wasNull()) - value = null; - - return value; - } - - /** - * 扩展获取列值。 - * - * @param cn - * @param rs - * @param column - * @param columnName - * @return - * @throws SQLException - */ - protected Object getColumnValueExt(Connection cn, ResultSet rs, Column column, String columnName) - throws SQLException - { - throw new UnsupportedOperationException("Get JDBC [" + column.getType() + "] type value is not supported"); - } - - /** - * 静默回滚。 - * - * @param cn - */ - public void rollbackSilently(Connection cn) - { - try - { - JdbcUtil.rollbackIfSupports(cn); - } - catch (Throwable t) - { - LOGGER.error("rollback connection exception", t); - } - } - - /** - * 静默提交。 - * - * @param cn - */ - public void commitSilently(Connection cn) - { - try - { - JdbcUtil.commitIfSupports(cn); - } - catch (Throwable t) - { - LOGGER.error("commit connection exception", t); - } - } - - public void closeIfClosable(List list) - { - if (list == null) - return; - - for (Object o : list) - closeIfClosable(o); - } - - public void closeIfClosable(Object... objs) - { - for (Object o : objs) - closeIfClosable(o); - } - - public boolean closeIfClosable(Object o) - { - if (o instanceof Closeable) - { - IOUtil.close((Closeable) o); - return true; - } - - return false; + return getColumnValue(cn, rs, column.getName(), column.getType()); } } diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/MysqlDialect.java b/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/MysqlDialect.java index 90afed51..2a645c37 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/MysqlDialect.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/MysqlDialect.java @@ -5,8 +5,8 @@ package org.datagear.persistence.support.dialect; import org.datagear.persistence.Order; -import org.datagear.persistence.Sql; import org.datagear.persistence.support.AbstractDialect; +import org.datagear.util.Sql; /** * Mysql方言。 diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/OracleDialect.java b/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/OracleDialect.java index cec563fe..1b32e678 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/OracleDialect.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/OracleDialect.java @@ -5,8 +5,8 @@ package org.datagear.persistence.support.dialect; import org.datagear.persistence.Order; -import org.datagear.persistence.Sql; import org.datagear.persistence.support.AbstractDialect; +import org.datagear.util.Sql; /** * Oracle方言。 diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/SqlServerDialect.java b/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/SqlServerDialect.java index 4139bede..f17a5dfb 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/SqlServerDialect.java +++ b/datagear-persistence/src/main/java/org/datagear/persistence/support/dialect/SqlServerDialect.java @@ -5,8 +5,8 @@ package org.datagear.persistence.support.dialect; import org.datagear.persistence.Order; -import org.datagear.persistence.Sql; import org.datagear.persistence.support.AbstractDialect; +import org.datagear.util.Sql; /** * SqlServer方言。 diff --git a/datagear-persistence/src/test/java/org/datagear/persistence/support/DefaultPersistenceManagerTest.java b/datagear-persistence/src/test/java/org/datagear/persistence/support/DefaultPersistenceManagerTest.java index c2e141f8..1d640b7e 100644 --- a/datagear-persistence/src/test/java/org/datagear/persistence/support/DefaultPersistenceManagerTest.java +++ b/datagear-persistence/src/test/java/org/datagear/persistence/support/DefaultPersistenceManagerTest.java @@ -5,12 +5,16 @@ package org.datagear.persistence.support; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.sql.Connection; +import java.util.List; import org.datagear.meta.Table; import org.datagear.meta.resolver.GenericDBMetaResolver; import org.datagear.persistence.DialectSource; +import org.datagear.persistence.PagingData; +import org.datagear.persistence.PagingQuery; import org.datagear.persistence.Row; import org.datagear.util.JdbcUtil; import org.datagear.util.test.DBTestSupport; @@ -78,4 +82,16 @@ public class DefaultPersistenceManagerTest extends DBTestSupport this.defaultPersistenceManager.delete(connection, table, row); } } + + @Test + public void pagingQueryTest() + { + Table table = this.genericDBMetaResolver.getTable(this.connection, "T_ACCOUNT"); + + PagingData pagingData = this.defaultPersistenceManager.pagingQuery(connection, table, + new PagingQuery(1, 1)); + List rows = pagingData.getItems(); + + assertTrue(rows.size() <= 1); + } } diff --git a/datagear-util/src/main/java/org/datagear/util/IOUtil.java b/datagear-util/src/main/java/org/datagear/util/IOUtil.java index d42e32ee..68376f05 100644 --- a/datagear-util/src/main/java/org/datagear/util/IOUtil.java +++ b/datagear-util/src/main/java/org/datagear/util/IOUtil.java @@ -25,6 +25,7 @@ import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.nio.charset.Charset; +import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; @@ -661,4 +662,46 @@ public class IOUtil { } } + + /** + * 如果是{@linkplain Closeable},则将其关闭。 + * + * @param list + */ + public static void closeIf(List list) + { + if (list == null) + return; + + for (Object o : list) + closeIf(o); + } + + /** + * 如果是{@linkplain Closeable},则将其关闭。 + * + * @param objs + */ + public static void closeIf(Object[] objs) + { + for (Object o : objs) + closeIf(o); + } + + /** + * 如果是{@linkplain Closeable},则将其关闭。 + * + * @param o + * @return + */ + public static boolean closeIf(Object o) + { + if (o instanceof Closeable) + { + close((Closeable) o); + return true; + } + + return false; + } } diff --git a/datagear-util/src/main/java/org/datagear/util/JdbcSupport.java b/datagear-util/src/main/java/org/datagear/util/JdbcSupport.java new file mode 100644 index 00000000..a1bf56e0 --- /dev/null +++ b/datagear-util/src/main/java/org/datagear/util/JdbcSupport.java @@ -0,0 +1,857 @@ +/* + * Copyright 2018 datagear.tech. All Rights Reserved. + */ + +package org.datagear.util; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLDataException; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLSyntaxErrorException; +import java.sql.SQLTimeoutException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Types; +import java.util.ArrayList; +import java.util.List; + +/** + * JDBC操作支持类。 + * + * @author datagear@163.com + * + */ +public class JdbcSupport +{ + /** + * 执行数目查询。 + * + * @param cn + * @param query + * @return + * @throws SQLException + */ + public long executeCountQuery(Connection cn, Sql query) throws SQLException + { + QueryResultSet qrs = null; + + try + { + long count = 0; + + qrs = executeQuery(cn, query, ResultSet.TYPE_FORWARD_ONLY); + + ResultSet rs = qrs.getResultSet(); + + if (rs.next()) + count = rs.getInt(1); + + return count; + } + finally + { + QueryResultSet.close(qrs); + } + } + + /** + * 执行查询。 + * + * @param cn + * @param sql + * @param resultSetType + * {@code ResultSet.TYPE_*} + * @return + * @throws SQLException + */ + public QueryResultSet executeQuery(Connection cn, Sql sql, int resultSetType) throws SQLException + { + PreparedStatement pst = null; + ResultSet rs = null; + List setParams = null; + + try + { + pst = createQueryPreparedStatement(cn, sql.getSqlValue(), resultSetType); + setParams = setParamValues(cn, pst, sql); + rs = pst.executeQuery(); + + return new QueryResultSet(pst, rs, setParams); + } + catch (SQLSyntaxErrorException | SQLDataException | SQLTimeoutException | SQLWarning e) + { + @JDBCCompatiblity("这些异常必定不是驱动程序的ResultSet.TYPE_SCROLL_*支持与否问题,不需要再降级处理") + SQLException e1 = e; + throw e1; + } + catch (SQLException e) + { + @JDBCCompatiblity("某些不支持ResultSet.TYPE_SCROLL_*的驱动程序不是在创建PreparedStatemen时报错," + + "而是在执行SQL的时候(比如SQLServer的聚集列存储索引),所以在这里检查,必要时降级重新执行查询") + int actualResultSetType = pst.getResultSetType(); + + if (ResultSet.TYPE_FORWARD_ONLY == actualResultSetType) + { + IOUtil.closeIf(setParams); + JdbcUtil.closeResultSet(rs); + JdbcUtil.closeStatement(pst); + + throw e; + } + else + { + JdbcUtil.closeResultSet(rs); + JdbcUtil.closeStatement(pst); + + @JDBCCompatiblity("降级为ResultSet.TYPE_FORWARD_ONLY重新执行") + QueryResultSet qrs = executeQuery(cn, sql, ResultSet.TYPE_FORWARD_ONLY); + return qrs; + } + } + } + + /** + * 执行更新。 + * + * @param cn + * @param sql + * @return + * @throws SQLException + */ + public int executeUpdate(Connection cn, Sql sql) throws SQLException + { + PreparedStatement pst = null; + List setParams = null; + + try + { + pst = createUpdatePreparedStatement(cn, sql.getSqlValue()); + setParams = setParamValues(cn, pst, sql); + + return pst.executeUpdate(); + } + finally + { + IOUtil.closeIf(setParams); + JdbcUtil.closeStatement(pst); + } + } + + /** + * 设置预编译SQL参数。 + * + * @param cn + * @param st + * @param sql + * @return + * @throws SQLException + */ + public List setParamValues(Connection cn, PreparedStatement st, Sql sql) throws SQLException + { + return setParamValues(cn, st, sql.getParamValues()); + } + + /** + * 设置预编译SQL参数。 + * + * @param cn + * @param st + * @param paramValues + * @return + * @throws SQLException + */ + public List setParamValues(Connection cn, PreparedStatement st, List paramValues) + throws SQLException + { + List setValues = new ArrayList<>(paramValues.size()); + + for (int i = 1; i <= paramValues.size(); i++) + { + Object setValue = setParamValue(cn, st, i, paramValues.get(i - 1)); + setValues.add(setValue); + } + + return setValues; + } + + /** + * 设置预编译SQL参数。 + * + * @param cn + * @param st + * @param paramValues + * @return + * @throws SQLException + */ + public Object[] setParamValues(Connection cn, PreparedStatement st, SqlParamValue... paramValues) + throws SQLException + { + Object[] setValues = new Object[paramValues.length]; + + for (int i = 1; i <= paramValues.length; i++) + setValues[i - 1] = setParamValue(cn, st, i, paramValues[i - 1]); + + return setValues; + } + + /** + * 创建用于查询的{@linkplain PreparedStatement}。 + * + * @param cn + * @param sql + * @param resultSetType + * @return + * @throws SQLException + */ + public PreparedStatement createQueryPreparedStatement(Connection cn, String sql, int resultSetType) + throws SQLException + { + if (ResultSet.TYPE_FORWARD_ONLY == resultSetType) + { + return cn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + } + else + { + PreparedStatement pst = null; + + try + { + pst = cn.prepareStatement(sql, resultSetType, ResultSet.CONCUR_READ_ONLY); + } + catch (SQLFeatureNotSupportedException e) + { + @JDBCCompatiblity("某些驱动程序不支持TYPE_SCROLL_INSENSITIVE,则降级获取") + PreparedStatement thenPst = cn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY); + pst = thenPst; + } + + return pst; + } + } + + /** + * 创建用于更新的{@linkplain PreparedStatement}。 + * + * @param cn + * @param sql + * @return + * @throws SQLException + */ + public PreparedStatement createUpdatePreparedStatement(Connection cn, String sql) throws SQLException + { + return cn.prepareStatement(sql); + } + + /** + * 创建用于查询的{@linkplain Statement}。 + * + * @param cn + * @param resultSetType + * @return + * @throws SQLException + */ + public Statement createQueryStatement(Connection cn, int resultSetType) throws SQLException + { + if (ResultSet.TYPE_FORWARD_ONLY == resultSetType) + { + return cn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + } + else + { + Statement st = null; + + try + { + st = cn.createStatement(resultSetType, ResultSet.CONCUR_READ_ONLY); + } + catch (SQLFeatureNotSupportedException e) + { + @JDBCCompatiblity("某些驱动程序不支持TYPE_SCROLL_INSENSITIVE,则降级获取") + Statement thenSt = cn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + st = thenSt; + } + + return st; + } + } + + /** + * 创建用于更新的{@linkplain Statement}。 + * + * @param cn + * @param sql + * @return + * @throws SQLException + */ + public Statement createUpdateStatement(Connection cn) throws SQLException + { + return cn.createStatement(); + } + + /** + * 设置{@linkplain PreparedStatement}的参数值。 + *

+ * 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Java Types Mapper to + * JDBC Types”表。 + *

+ * + * @param cn + * @param st + * @param paramIndex + * @param paramValue + * @return + * @throws SQLException + */ + @JDBCCompatiblity("某些驱动程序不支持PreparedStatement.setObject方法(比如:Hive JDBC),所以这里没有使用") + public Object setParamValue(Connection cn, PreparedStatement st, int paramIndex, SqlParamValue paramValue) + throws SQLException + { + int sqlType = paramValue.getType(); + Object value = paramValue.getValue(); + + if (value == null) + { + st.setNull(paramIndex, sqlType); + return null; + } + + switch (sqlType) + { + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + { + if (value instanceof String) + st.setString(paramIndex, (String) value); + else if (value instanceof Reader) + st.setCharacterStream(paramIndex, (Reader) value); + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.NUMERIC: + case Types.DECIMAL: + { + BigDecimal v = null; + + if (value instanceof BigDecimal) + v = (BigDecimal) value; + else if (value instanceof BigInteger) + v = new BigDecimal((BigInteger) value); + else if (value instanceof Number) + v = new BigDecimal(((Number) value).doubleValue()); + + if (v != null) + { + st.setBigDecimal(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.BIT: + case Types.BOOLEAN: + { + if (value instanceof Boolean) + st.setBoolean(paramIndex, (Boolean) value); + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + { + Integer v = null; + + if (value instanceof Integer) + v = (Integer) value; + else if (value instanceof Number) + v = ((Number) value).intValue(); + + if (v != null) + { + st.setInt(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.BIGINT: + { + Long v = null; + + if (value instanceof Long) + v = (Long) value; + else if (value instanceof Number) + v = ((Number) value).longValue(); + + if (v != null) + { + st.setLong(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.REAL: + { + Float v = null; + + if (value instanceof Float) + v = (Float) value; + else if (value instanceof Number) + v = ((Number) value).floatValue(); + + if (v != null) + { + st.setFloat(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.FLOAT: + case Types.DOUBLE: + { + Double v = null; + + if (value instanceof Double) + v = (Double) value; + else if (value instanceof Number) + v = ((Number) value).doubleValue(); + + if (v != null) + { + st.setDouble(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + { + if (value instanceof byte[]) + st.setBytes(paramIndex, (byte[]) value); + else if (value instanceof InputStream) + st.setBinaryStream(paramIndex, (InputStream) value); + else if (value instanceof File) + { + InputStream v = getInputStreamForSql((File) value); + st.setBinaryStream(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.DATE: + { + java.sql.Date v = null; + + if (value instanceof java.sql.Date) + v = (java.sql.Date) value; + else if (value instanceof java.util.Date) + v = new java.sql.Date(((java.util.Date) value).getTime()); + + if (v != null) + { + st.setDate(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.TIME: + { + java.sql.Time v = null; + + if (value instanceof java.sql.Time) + v = (java.sql.Time) value; + else if (value instanceof java.util.Date) + v = new java.sql.Time(((java.util.Date) value).getTime()); + + if (v != null) + { + st.setTime(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.TIMESTAMP: + { + java.sql.Timestamp v = null; + + if (value instanceof java.sql.Timestamp) + v = (java.sql.Timestamp) value; + else if (value instanceof java.util.Date) + v = new java.sql.Timestamp(((java.util.Date) value).getTime()); + + if (v != null) + { + st.setTimestamp(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.CLOB: + { + if (value instanceof Clob) + st.setClob(paramIndex, (Clob) value); + else if (value instanceof Reader) + st.setClob(paramIndex, (Reader) value); + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.BLOB: + { + if (value instanceof Blob) + st.setBlob(paramIndex, (Blob) value); + else if (value instanceof InputStream) + st.setBlob(paramIndex, (InputStream) value); + else if (value instanceof File) + { + InputStream v = getInputStreamForSql((File) value); + st.setBlob(paramIndex, v); + value = v; + } + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.NCHAR: + case Types.NVARCHAR: + case Types.LONGNVARCHAR: + { + if (value instanceof String) + st.setNString(paramIndex, (String) value); + else if (value instanceof Reader) + st.setNCharacterStream(paramIndex, (Reader) value); + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.NCLOB: + { + if (value instanceof NClob) + st.setNClob(paramIndex, (NClob) value); + else if (value instanceof Reader) + st.setNClob(paramIndex, (Reader) value); + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + case Types.SQLXML: + { + if (value instanceof SQLXML) + st.setSQLXML(paramIndex, (SQLXML) value); + else + value = setParamValueExt(cn, st, paramIndex, paramValue); + + break; + } + + default: + value = setParamValueExt(cn, st, paramIndex, paramValue); + } + + return value; + } + + /** + * 扩展设置{@linkplain SqlParamValue}。 + * + * @param cn + * @param st + * @param paramIndex + * @param paramValue + * @return + * @throws SQLException + */ + protected Object setParamValueExt(Connection cn, PreparedStatement st, int paramIndex, SqlParamValue paramValue) + throws SQLException + { + throw new UnsupportedOperationException("Set JDBC [" + paramValue.getType() + "] type value is not supported"); + } + + protected InputStream getInputStreamForSql(File file) throws SQLException + { + try + { + return IOUtil.getInputStream(file); + } + catch (FileNotFoundException e) + { + throw new SQLException("File [" + file.getAbsolutePath() + "] not found"); + } + } + + /** + * 获取列值。 + *

+ * 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Type Conversions + * Supported by ResultSet getter Methods”表,并且使用其中的最佳方法。 + *

+ * + * @param cn + * @param rs + * @param column + * @return + * @throws SQLException + */ + public Object getColumnValue(Connection cn, ResultSet rs, String columnName, int sqlType) throws SQLException + { + Object value = null; + + switch (sqlType) + { + case Types.TINYINT: + { + value = rs.getByte(columnName); + break; + } + + case Types.SMALLINT: + { + value = rs.getShort(columnName); + break; + } + + case Types.INTEGER: + { + value = rs.getInt(columnName); + break; + } + + case Types.BIGINT: + { + value = rs.getLong(columnName); + break; + } + + case Types.REAL: + { + value = rs.getFloat(columnName); + break; + } + + case Types.FLOAT: + case Types.DOUBLE: + { + value = rs.getDouble(columnName); + break; + } + + case Types.DECIMAL: + case Types.NUMERIC: + { + value = rs.getBigDecimal(columnName); + break; + } + + case Types.BIT: + { + value = rs.getBoolean(columnName); + break; + } + + case Types.BOOLEAN: + { + value = rs.getBoolean(columnName); + break; + } + + case Types.CHAR: + case Types.VARCHAR: + { + value = rs.getString(columnName); + break; + } + + case Types.LONGVARCHAR: + { + value = rs.getCharacterStream(columnName); + break; + } + + case Types.BINARY: + case Types.VARBINARY: + { + value = rs.getBytes(columnName); + break; + } + + case Types.LONGVARBINARY: + { + value = rs.getBinaryStream(columnName); + break; + } + + case Types.DATE: + { + value = rs.getDate(columnName); + break; + } + + case Types.TIME: + { + value = rs.getTime(columnName); + break; + } + + case Types.TIMESTAMP: + { + value = rs.getTimestamp(columnName); + break; + } + + case Types.CLOB: + { + value = rs.getClob(columnName); + break; + } + + case Types.BLOB: + { + value = rs.getBlob(columnName); + break; + } + + case Types.NCHAR: + case Types.NVARCHAR: + { + value = rs.getNString(columnName); + break; + } + + case Types.LONGNVARCHAR: + { + value = rs.getNCharacterStream(columnName); + break; + } + + case Types.NCLOB: + { + value = rs.getNClob(columnName); + break; + } + + case Types.SQLXML: + { + value = rs.getSQLXML(columnName); + break; + } + + default: + value = getColumnValueExt(cn, rs, columnName, sqlType); + break; + } + + if (rs.wasNull()) + value = null; + + return value; + } + + /** + * 扩展获取列值。 + * + * @param cn + * @param rs + * @param columnName + * @param sqlType + * @return + * @throws SQLException + */ + protected Object getColumnValueExt(Connection cn, ResultSet rs, String columnName, int sqlType) throws SQLException + { + throw new UnsupportedOperationException("Get JDBC [" + sqlType + "] type value is not supported"); + } + + /** + * 将一个未移动过游标的{@linkplain ResultSet}游标前移至指定行之前。 + * + * @param rs + * @param rowIndex + * 行号,以{@code 1}开始 + * @throws SQLException + */ + public void forwardBefore(ResultSet rs, int rowIndex) throws SQLException + { + // 第一行不做任何操作,避免不必要的调用可能导致底层不支持而报错 + if (rowIndex == 1) + return; + + try + { + rs.absolute(rowIndex - 1); + } + catch (SQLException e) + { + @JDBCCompatiblity("避免驱动程序或者ResultSet不支持absolute而抛出异常") + int i = 1; + for (; i < rowIndex; i++) + { + if (!rs.next()) + break; + } + } + } +} diff --git a/datagear-util/src/main/java/org/datagear/util/JdbcUtil.java b/datagear-util/src/main/java/org/datagear/util/JdbcUtil.java index 86b74580..31348374 100644 --- a/datagear-util/src/main/java/org/datagear/util/JdbcUtil.java +++ b/datagear-util/src/main/java/org/datagear/util/JdbcUtil.java @@ -5,20 +5,12 @@ package org.datagear.util; import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Blob; -import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; -import java.sql.NClob; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLXML; import java.sql.Statement; import java.sql.Types; -import java.util.List; /** * JDBC工具支持类。 @@ -33,526 +25,6 @@ public class JdbcUtil throw new UnsupportedOperationException(); } - /** - * 设置{@linkplain PreparedStatement}的参数值,并在必要时进行数据类型转换。 - *

- * 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Java Types Mapper to - * JDBC Types”表。 - *

- * - * @param cn - * @param st - * @param paramIndex - * @param sqlType - * @param paramValue - * @throws SQLException - * @throws UnsupportedOperationException - */ - @JDBCCompatiblity("某些驱动程序不支持PreparedStatement.setObject方法(比如:Hive JDBC),所以这里没有使用") - public static void setParamValue(Connection cn, PreparedStatement st, int paramIndex, int sqlType, - Object paramValue) throws SQLException, UnsupportedOperationException - { - if (paramValue == null) - { - st.setNull(paramIndex, sqlType); - return; - } - - switch (sqlType) - { - case Types.CHAR: - case Types.VARCHAR: - case Types.LONGVARCHAR: - { - String value = null; - - if (paramValue instanceof String) - value = (String) paramValue; - else - value = paramValue.toString(); - - st.setString(paramIndex, value); - - break; - } - - case Types.NUMERIC: - case Types.DECIMAL: - { - BigDecimal value = null; - - if (paramValue instanceof BigDecimal) - value = (BigDecimal) paramValue; - else if (paramValue instanceof BigInteger) - value = new BigDecimal((BigInteger) paramValue); - else if (paramValue instanceof Number) - value = new BigDecimal(((Number) paramValue).doubleValue()); - else if (paramValue instanceof String) - value = new BigDecimal((String) paramValue); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setBigDecimal(paramIndex, value); - - break; - } - - case Types.BIT: - case Types.BOOLEAN: - { - boolean value = false; - - if (paramValue instanceof Boolean) - value = (Boolean) paramValue; - else if (paramValue instanceof String) - { - String str = (String) paramValue; - value = ("true".equalsIgnoreCase(str) || "1".equals(str) || "on".equalsIgnoreCase(str)); - } - else if (paramValue instanceof Number) - value = (((Number) paramValue).intValue() > 0); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setBoolean(paramIndex, value); - - break; - } - - case Types.TINYINT: - case Types.SMALLINT: - case Types.INTEGER: - { - Integer value = null; - - if (paramValue instanceof Integer) - value = (Integer) paramValue; - else if (paramValue instanceof Number) - value = ((Number) paramValue).intValue(); - else if (paramValue instanceof String) - value = Integer.parseInt((String) paramValue); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setInt(paramIndex, value); - - break; - } - - case Types.BIGINT: - { - Long value = null; - - if (paramValue instanceof Long) - value = (Long) paramValue; - else if (paramValue instanceof Number) - value = ((Number) paramValue).longValue(); - else if (paramValue instanceof String) - value = Long.parseLong((String) paramValue); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setLong(paramIndex, value); - - break; - } - - case Types.REAL: - { - Float value = null; - - if (paramValue instanceof Float) - value = (Float) paramValue; - else if (paramValue instanceof Number) - value = ((Number) paramValue).floatValue(); - else if (paramValue instanceof String) - value = Float.parseFloat((String) paramValue); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setFloat(paramIndex, value); - - break; - } - - case Types.FLOAT: - case Types.DOUBLE: - { - Double value = null; - - if (paramValue instanceof Double) - value = (Double) paramValue; - else if (paramValue instanceof Number) - value = ((Number) paramValue).doubleValue(); - else if (paramValue instanceof String) - value = Double.parseDouble((String) paramValue); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setDouble(paramIndex, value); - - break; - } - - case Types.BINARY: - case Types.VARBINARY: - case Types.LONGVARBINARY: - { - byte[] value = null; - - if (paramValue instanceof byte[]) - value = (byte[]) paramValue; - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setBytes(paramIndex, value); - - break; - } - - case Types.DATE: - { - java.sql.Date value = null; - - if (paramValue instanceof java.sql.Date) - value = (java.sql.Date) paramValue; - else if (paramValue instanceof java.util.Date) - value = new java.sql.Date(((java.util.Date) paramValue).getTime()); - else if (paramValue instanceof Number) - value = new java.sql.Date(((Number) paramValue).longValue()); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setDate(paramIndex, value); - - break; - } - - case Types.TIME: - { - java.sql.Time value = null; - - if (paramValue instanceof java.sql.Time) - value = (java.sql.Time) paramValue; - else if (paramValue instanceof java.util.Date) - value = new java.sql.Time(((java.util.Date) paramValue).getTime()); - else if (paramValue instanceof Number) - value = new java.sql.Time(((Number) paramValue).longValue()); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setTime(paramIndex, value); - - break; - } - - case Types.TIMESTAMP: - { - java.sql.Timestamp value = null; - - if (paramValue instanceof java.sql.Timestamp) - value = (java.sql.Timestamp) paramValue; - else if (paramValue instanceof java.util.Date) - value = new java.sql.Timestamp(((java.util.Date) paramValue).getTime()); - else if (paramValue instanceof Number) - value = new java.sql.Timestamp(((Number) paramValue).longValue()); - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setTimestamp(paramIndex, value); - - break; - } - - case Types.CLOB: - { - Clob clob = null; - - if (paramValue instanceof Clob) - { - clob = (Clob) paramValue; - } - else if (paramValue instanceof String) - { - String str = (String) paramValue; - - clob = cn.createClob(); - clob.setString(1, str); - } - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setClob(paramIndex, clob); - - break; - } - - case Types.BLOB: - { - Blob blob = null; - - if (paramValue instanceof Blob) - { - blob = (Blob) paramValue; - } - else if (paramValue instanceof byte[]) - { - byte[] bytes = (byte[]) paramValue; - blob = cn.createBlob(); - blob.setBytes(1, bytes); - } - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setBlob(paramIndex, blob); - - break; - } - - case Types.NCHAR: - case Types.NVARCHAR: - case Types.LONGNVARCHAR: - { - String value = null; - - if (paramValue instanceof String) - value = (String) paramValue; - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setNString(paramIndex, value); - break; - } - - case Types.NCLOB: - { - NClob nclob = null; - - if (paramValue instanceof NClob) - { - nclob = (NClob) paramValue; - } - else if (paramValue instanceof String) - { - String str = (String) paramValue; - nclob = cn.createNClob(); - nclob.setString(1, str); - } - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setNClob(paramIndex, nclob); - break; - } - - case Types.SQLXML: - { - SQLXML sqlxml = null; - - if (paramValue instanceof SQLXML) - { - sqlxml = (SQLXML) paramValue; - } - if (paramValue instanceof String) - { - String str = (String) paramValue; - sqlxml = cn.createSQLXML(); - sqlxml.setString(str); - } - else - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value for type [" - + paramValue.getClass().getName() + "] is not supported"); - - st.setSQLXML(paramIndex, sqlxml); - break; - } - - default: - - throw new UnsupportedOperationException("Set JDBC [" + sqlType + "] type value is not supported"); - } - } - - /** - * 获取指定类型的列值。 - * - * @param rs - * @param row - * @param columnIndex - * @param targetType - * @return - * @throws SQLException - */ - public static Object getColumnValue(ResultSet rs, long row, int columnIndex, Class targetType) - throws SQLException - { - if (String.class.equals(targetType)) - { - return rs.getString(columnIndex); - } - else if (int.class.equals(targetType)) - { - return rs.getInt(columnIndex); - } - else if (Integer.class.equals(targetType)) - { - Integer v = rs.getInt(columnIndex); - - return (rs.wasNull() ? null : v); - } - else if (boolean.class.equals(targetType)) - { - return rs.getBoolean(columnIndex); - } - else if (Boolean.class.equals(targetType)) - { - Boolean v = rs.getBoolean(columnIndex); - - return (rs.wasNull() ? null : v); - } - else if (long.class.equals(targetType)) - { - return rs.getLong(columnIndex); - } - else if (Long.class.equals(targetType)) - { - long v = rs.getLong(columnIndex); - - return (rs.wasNull() ? null : v); - } - else if (short.class.equals(targetType)) - { - return rs.getShort(columnIndex); - } - else if (Short.class.equals(targetType)) - { - short v = rs.getShort(columnIndex); - - return (rs.wasNull() ? null : v); - } - else if (float.class.equals(targetType)) - { - return rs.getFloat(columnIndex); - } - else if (Float.class.equals(targetType)) - { - float v = rs.getFloat(columnIndex); - - return (rs.wasNull() ? null : v); - } - else if (double.class.equals(targetType)) - { - return rs.getDouble(columnIndex); - } - else if (Double.class.equals(targetType)) - { - double v = rs.getDouble(columnIndex); - - return (rs.wasNull() ? null : v); - } - else if (java.util.Date.class.equals(targetType)) - { - return rs.getDate(columnIndex); - } - else if (BigDecimal.class.equals(targetType)) - { - return rs.getBigDecimal(columnIndex); - } - else if (BigInteger.class.equals(targetType)) - { - BigDecimal bd = rs.getBigDecimal(columnIndex); - - return (bd == null ? null : bd.toBigInteger()); - } - else if (byte.class.equals(targetType)) - { - return rs.getByte(columnIndex); - } - else if (Byte.class.equals(targetType)) - { - byte v = rs.getByte(columnIndex); - - return (rs.wasNull() ? null : v); - } - else if (byte[].class.equals(targetType)) - { - return rs.getBytes(columnIndex); - } - else if (char.class.equals(targetType)) - { - String v = rs.getString(columnIndex); - - return (v == null ? (char) 0 : v.charAt(0)); - } - else if (Character.class.equals(targetType)) - { - String v = rs.getString(columnIndex); - - return (v == null ? null : v.charAt(0)); - } - else if (java.sql.Date.class.equals(targetType)) - { - return rs.getDate(columnIndex); - } - else if (java.sql.Timestamp.class.equals(targetType)) - { - return rs.getTimestamp(columnIndex); - } - else if (java.sql.Time.class.equals(targetType)) - { - return rs.getTime(columnIndex); - } - else if (Enum.class.isAssignableFrom(targetType)) - { - String enumName = rs.getString(columnIndex); - - if (rs.wasNull() || enumName == null || enumName.isEmpty()) - return null; - else - { - @SuppressWarnings({ "unchecked", "rawtypes" }) - Enum em = Enum.valueOf((Class) targetType, enumName); - - return em; - } - } - else if (Object.class.equals(targetType)) - { - return rs.getObject(columnIndex); - } - else - throw new UnsupportedOperationException("Getting [" + ResultSet.class.getName() - + "] column value for type [" + targetType.getName() + "] is not supported"); - } - - /** - * 获取指定对象的JDBC类型。 - * - * @param obj - * @return - */ - public static int getJdbcType(Object obj) - { - if (obj == null) - return Types.NULL; - else - return getJdbcType(obj.getClass()); - } - /** * 将字符串转换为指定SQL类型的数值。 *

@@ -622,110 +94,6 @@ public class JdbcUtil } } - /** - * 获取指定类的JDBC类型。 - * - * @param clazz - * @return - */ - public static int getJdbcType(Class clazz) - { - if (String.class.equals(clazz)) - { - return Types.VARCHAR; - } - else if (boolean.class.equals(clazz) || Boolean.class.equals(clazz)) - { - return Types.BOOLEAN; - } - else if (int.class.equals(clazz) || Integer.class.equals(clazz)) - { - return Types.INTEGER; - } - else if (long.class.equals(clazz) || Long.class.equals(clazz)) - { - return Types.BIGINT; - } - else if (float.class.equals(clazz) || Float.class.equals(clazz)) - { - return Types.FLOAT; - } - else if (double.class.equals(clazz) || Double.class.equals(clazz)) - { - return Types.DOUBLE; - } - else if (java.math.BigDecimal.class.isAssignableFrom(clazz)) - { - return Types.NUMERIC; - } - else if (java.math.BigInteger.class.isAssignableFrom(clazz)) - { - return Types.NUMERIC; - } - else if (java.sql.Date.class.isAssignableFrom(clazz)) - { - return Types.DATE; - } - else if (java.sql.Time.class.isAssignableFrom(clazz)) - { - return Types.TIME; - } - else if (java.sql.Timestamp.class.isAssignableFrom(clazz)) - { - return Types.TIMESTAMP; - } - else if (java.util.Date.class.isAssignableFrom(clazz)) - { - return Types.DATE; - } - else if (byte.class.equals(clazz) || Byte.class.equals(clazz)) - { - return Types.TINYINT; - } - else if (short.class.equals(clazz) || Short.class.equals(clazz)) - { - return Types.SMALLINT; - } - else if (char.class.equals(clazz) || Character.class.equals(clazz)) - { - return Types.CHAR; - } - else if (byte[].class.equals(clazz) || Byte[].class.equals(clazz)) - { - return Types.BINARY; - } - else if (java.sql.Clob.class.isAssignableFrom(clazz)) - { - return Types.CLOB; - } - else if (java.sql.Blob.class.isAssignableFrom(clazz)) - { - return Types.BLOB; - } - else if (java.sql.Array.class.isAssignableFrom(clazz)) - { - return Types.ARRAY; - } - else if (java.sql.Struct.class.isAssignableFrom(clazz)) - { - return Types.STRUCT; - } - else if (java.sql.Ref.class.isAssignableFrom(clazz)) - { - return Types.REF; - } - else if (java.net.URL.class.isAssignableFrom(clazz)) - { - return Types.REF; - } - else if (Class.class.equals(clazz)) - { - return Types.JAVA_OBJECT; - } - else - throw new UnsupportedOperationException("Unsupported Java type [" + clazz + "] for getting JDBC type"); - } - /** * 关闭{@linkplain Connection}。 *

@@ -792,6 +160,22 @@ public class JdbcUtil } } + /** + * 静默提交。 + * + * @param cn + */ + public static void commitSilently(Connection cn) + { + try + { + commitIfSupports(cn); + } + catch (Throwable t) + { + } + } + /** * 提交。 * @@ -811,6 +195,22 @@ public class JdbcUtil return true; } + /** + * 静默回滚。 + * + * @param cn + */ + public static void rollbackSilently(Connection cn) + { + try + { + rollbackIfSupports(cn); + } + catch (Throwable t) + { + } + } + /** * 回滚。 * @@ -841,27 +241,6 @@ public class JdbcUtil return cn.isReadOnly(); } - /** - * 设置{@linkplain ResultSet#setFetchSize(int)}。 - * - * @param rs - * @param fetchSize - * @return - */ - public static boolean setFetchSizeSilently(ResultSet rs, int fetchSize) - { - try - { - rs.setFetchSize(fetchSize); - - return true; - } - catch (SQLException e) - { - return false; - } - } - /** * 设置为只读。 * @@ -946,273 +325,4 @@ public class JdbcUtil return null; } } - - /** - * 将一个未移动过游标的{@linkplain ResultSet}游标移动至指定行之前。 - * - * @param rs - * @param row - * @throws SQLException - */ - @JDBCCompatiblity("避免有驱动程序不支持absolute而抛出异常") - public static void moveToBeforeRow(ResultSet rs, int row) throws SQLException - { - // 第一行不做任何操作,避免不必要的调用可能导致底层不支持而报错 - if (row == 1) - return; - - try - { - rs.absolute(row - 1); - } - catch (SQLException e) - { - for (int i = 1; i < row; i++) - { - if (!rs.next()) - break; - } - } - } - - /** - * 创建用于执行查询语句的{@linkplain Statement}。 - * - * @param cn - * @return - * @throws SQLException - */ - @JDBCCompatiblity("避免有驱动程序不支持TYPE_SCROLL_INSENSITIVE而抛出异常") - public static Statement createQueryStatement(Connection cn) throws SQLException - { - try - { - return cn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - } - catch (SQLFeatureNotSupportedException e) - { - return cn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - } - } - - /** - * 创建用于执行查询语句的{@linkplain PreparedStatement}。 - * - * @param cn - * @param sql - * @return - * @throws SQLException - */ - @JDBCCompatiblity("避免有驱动程序不支持TYPE_SCROLL_INSENSITIVE而抛出异常") - public static PreparedStatement createQueryPreparedStatement(Connection cn, String sql) throws SQLException - { - try - { - return cn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - } - catch (SQLFeatureNotSupportedException e) - { - // 驱动程序不支持TYPE_SCROLL_INSENSITIVE时 - return cn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - } - } - - /** - * 执行查询。 - * - * @param cn - * @param sql - * @return - * @throws SQLException - */ - public static QueryResultSet executeQuery(Connection cn, String sql) throws SQLException - { - return executeQuery(cn, sql, null); - } - - /** - * 执行查询。 - * - * @param cn - * @param sql - * @param fetchSize - * @return - * @throws SQLException - */ - public static QueryResultSet executeQuery(Connection cn, String sql, Integer fetchSize) throws SQLException - { - Statement st = createQueryStatement(cn); - ResultSet rs = null; - - try - { - rs = st.executeQuery(sql); - return new QueryResultSet(st, rs); - } - catch (SQLException e) - { - if (ResultSet.TYPE_FORWARD_ONLY == st.getResultSetType()) - throw e; - else - { - JdbcUtil.closeResultSet(rs); - JdbcUtil.closeStatement(st); - } - } - - @JDBCCompatiblity("可能是查询SQL语句不支持ResultSet.TYPE_SCROLL_*(比如SQLServer的聚集列存储索引)," - + "因此,这里再降级为ResultSet.TYPE_FORWARD_ONLY再执行查询") - // TODO 如果是SQL语法错误,则不应再降级执行 - QueryResultSet queryResultSet = null; - - st = cn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - - if (fetchSize != null && fetchSize >= 0) - st.setFetchSize(fetchSize); - - rs = st.executeQuery(sql); - - queryResultSet = new QueryResultSet(st, rs); - - return queryResultSet; - } - - /** - * 执行查询。 - * - * @param cn - * @param sql - * @param paramTypes - * @param params - * @return - * @throws SQLException - */ - public static QueryResultSet executeQuery(Connection cn, String sql, List paramTypes, List params) - throws SQLException - { - return executeQuery(cn, sql, null, paramTypes, params); - } - - /** - * 执行查询。 - * - * @param cn - * @param sql - * @param fetchSize - * @param paramTypes - * @param params - * @return - * @throws SQLException - */ - public static QueryResultSet executeQuery(Connection cn, String sql, Integer fetchSize, List paramTypes, - List params) throws SQLException - { - PreparedStatement pst = createQueryPreparedStatement(cn, sql); - ResultSet rs = null; - - for (int i = 0, len = params.size(); i < len; i++) - setParamValue(cn, pst, i + 1, paramTypes.get(i), params.get(i)); - - try - { - rs = pst.executeQuery(); - return new QueryResultSet(pst, rs); - } - catch (SQLException e) - { - if (ResultSet.TYPE_FORWARD_ONLY == pst.getResultSetType()) - throw e; - else - { - JdbcUtil.closeResultSet(rs); - JdbcUtil.closeStatement(pst); - } - } - - @JDBCCompatiblity("可能是查询SQL语句不支持ResultSet.TYPE_SCROLL_*(比如SQLServer的聚集列存储索引)," - + "因此,这里再降级为ResultSet.TYPE_FORWARD_ONLY再执行查询") - // TODO 如果是SQL语法错误,则不应再降级执行 - QueryResultSet queryResultSet = null; - - pst = cn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - - for (int i = 0, len = params.size(); i < len; i++) - setParamValue(cn, pst, i + 1, paramTypes.get(i), params.get(i)); - - if (fetchSize != null && fetchSize >= 0) - pst.setFetchSize(fetchSize); - - rs = pst.executeQuery(); - - queryResultSet = new QueryResultSet(pst, rs); - - return queryResultSet; - } - - /** - * SQL查询结果集。 - * - * @author datagear@163.com - * - */ - public static class QueryResultSet - { - private Statement statement; - - private ResultSet resultSet; - - public QueryResultSet() - { - super(); - } - - public QueryResultSet(Statement statement, ResultSet resultSet) - { - super(); - this.statement = statement; - this.resultSet = resultSet; - } - - public Statement getStatement() - { - return statement; - } - - public void setStatement(Statement statement) - { - this.statement = statement; - } - - public ResultSet getResultSet() - { - return resultSet; - } - - public void setResultSet(ResultSet resultSet) - { - this.resultSet = resultSet; - } - - public boolean isPreparedStatement() - { - return (this.statement instanceof PreparedStatement); - } - - public PreparedStatement getPreparedStatement() - { - return (PreparedStatement) this.statement; - } - - /** - * 关闭。 - *

- * 此方法不会抛出任何异常。 - *

- */ - public void close() - { - closeResultSet(this.resultSet); - closeStatement(this.statement); - } - } } diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/support/QueryResultSet.java b/datagear-util/src/main/java/org/datagear/util/QueryResultSet.java similarity index 85% rename from datagear-persistence/src/main/java/org/datagear/persistence/support/QueryResultSet.java rename to datagear-util/src/main/java/org/datagear/util/QueryResultSet.java index 5fb8f1bf..c6472da0 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/support/QueryResultSet.java +++ b/datagear-util/src/main/java/org/datagear/util/QueryResultSet.java @@ -2,17 +2,13 @@ * Copyright 2018 datagear.tech. All Rights Reserved. */ -package org.datagear.persistence.support; +package org.datagear.util; -import java.io.Closeable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.List; -import org.datagear.util.IOUtil; -import org.datagear.util.JdbcUtil; - /** * 查询结果集。 * @@ -97,14 +93,8 @@ public class QueryResultSet */ public void close() { - if (this.params != null) - { - for (Object param : this.params) - { - if (param instanceof Closeable) - IOUtil.close((Closeable) param); - } - } + if (this.hasParam()) + IOUtil.closeIf(this.params); JdbcUtil.closeResultSet(this.resultSet); JdbcUtil.closeStatement(this.statement); diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/Sql.java b/datagear-util/src/main/java/org/datagear/util/Sql.java similarity index 99% rename from datagear-persistence/src/main/java/org/datagear/persistence/Sql.java rename to datagear-util/src/main/java/org/datagear/util/Sql.java index daf96e68..391ba8e9 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/Sql.java +++ b/datagear-util/src/main/java/org/datagear/util/Sql.java @@ -2,7 +2,7 @@ * Copyright 2018 datagear.tech. All Rights Reserved. */ -package org.datagear.persistence; +package org.datagear.util; import java.io.Serializable; import java.util.ArrayList; diff --git a/datagear-persistence/src/main/java/org/datagear/persistence/SqlParamValue.java b/datagear-util/src/main/java/org/datagear/util/SqlParamValue.java similarity index 95% rename from datagear-persistence/src/main/java/org/datagear/persistence/SqlParamValue.java rename to datagear-util/src/main/java/org/datagear/util/SqlParamValue.java index e848f20a..ce247b85 100644 --- a/datagear-persistence/src/main/java/org/datagear/persistence/SqlParamValue.java +++ b/datagear-util/src/main/java/org/datagear/util/SqlParamValue.java @@ -2,7 +2,7 @@ * Copyright 2018 datagear.tech. All Rights Reserved. */ -package org.datagear.persistence; +package org.datagear.util; /** * SQL参数值。