forked from p85126437/datagear
重构JDBC相关工具类,将部分公用工具类移至util模块内
This commit is contained in:
parent
afe47a2a5c
commit
03e0a09778
|
@ -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<String, Object> myParamValues = new HashMap<String, Object>();
|
||||
HashMap<String, Object> myParamValues = new HashMap<>();
|
||||
if (paramValues != null)
|
||||
myParamValues.putAll(paramValues);
|
||||
|
||||
|
|
|
@ -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<Map<String, ?>> resolveDatas(Connection cn, ResultSet rs, List<DataSetProperty> properties)
|
||||
throws SQLException
|
||||
{
|
||||
List<Map<String, ?>> datas = new ArrayList<Map<String, ?>>();
|
||||
List<Map<String, ?>> datas = new ArrayList<>();
|
||||
|
||||
ResultSetMetaData rsMeta = rs.getMetaData();
|
||||
int[] rsColumns = resolveResultsetColumns(properties, rsMeta);
|
||||
|
||||
while (rs.next())
|
||||
{
|
||||
Map<String, Object> row = new HashMap<String, Object>();
|
||||
Map<String, Object> 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<DataSetProperty> properties = new ArrayList<DataSetProperty>(columnCount);
|
||||
List<DataSetProperty> properties = new ArrayList<>(columnCount);
|
||||
|
||||
for (int i = 1; i <= columnCount; i++)
|
||||
{
|
||||
|
@ -619,7 +619,7 @@ public class SqlDataSetSupport
|
|||
|
||||
return dataType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析SQL语句参数名列表。
|
||||
*
|
||||
|
|
|
@ -192,11 +192,11 @@ public abstract class AbstractDevotedDataExchangeService<T extends DataExchange>
|
|||
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
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.datagear.persistence;
|
|||
import java.sql.ResultSet;
|
||||
|
||||
import org.datagear.meta.Table;
|
||||
import org.datagear.util.Sql;
|
||||
|
||||
/**
|
||||
* 数据库方言。
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}。
|
||||
|
|
|
@ -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<String, DialectBuilder> dialectBuilderCache = new ConcurrentHashMap<String, DialectBuilder>();
|
||||
private ConcurrentMap<String, DialectBuilder> dialectBuilderCache = new ConcurrentHashMap<>();
|
||||
|
||||
public DefaultDialectSource()
|
||||
{
|
||||
|
@ -52,7 +53,7 @@ public class DefaultDialectSource extends PersistenceSupport implements DialectS
|
|||
{
|
||||
super();
|
||||
this.dbMetaResolver = dbMetaResolver;
|
||||
this.dialectBuilders = new ArrayList<DialectBuilder>();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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<Row> rows = executeListQuery(cn, table, sql, rowMapper);
|
||||
List<Row> 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<Row> pagingQuery(Connection cn, Table table, PagingQuery pagingQuery)
|
||||
throws PersistenceException
|
||||
public PagingData<Row> 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<Row> pagingData = new PagingData<>(pagingQuery.getPage(), total, pagingQuery.getPageSize());
|
||||
|
||||
Sql query = null;
|
||||
|
||||
List<Row> 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<Row> 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
|
||||
*/
|
||||
|
|
|
@ -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<Row> 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<Row> 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<Row> executeListQuery(Connection cn, Table table, Sql sql, RowMapper mapper) throws PersistenceException
|
||||
public List<Row> 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<Row> executeListQuery(Connection cn, Table table, Sql sql, int startRow, int count, RowMapper mapper)
|
||||
throws PersistenceException
|
||||
public List<Row> 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<Object> 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<Object> 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<Object> setParamValues(Connection cn, PreparedStatement st, Sql sql) throws SQLException
|
||||
{
|
||||
return setParamValues(cn, st, sql.getParamValues());
|
||||
}
|
||||
|
||||
public List<Object> setParamValues(Connection cn, PreparedStatement st, List<SqlParamValue> paramValues)
|
||||
throws SQLException
|
||||
{
|
||||
List<Object> 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}的参数值。
|
||||
* <p>
|
||||
* 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Java Types Mapper to
|
||||
* JDBC Types”表。
|
||||
* </p>
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列值。
|
||||
* <p>
|
||||
* 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Type Conversions
|
||||
* Supported by ResultSet getter Methods”表,并且使用其中的最佳方法。
|
||||
* </p>
|
||||
*
|
||||
* @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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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方言。
|
||||
|
|
|
@ -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方言。
|
||||
|
|
|
@ -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方言。
|
||||
|
|
|
@ -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<Row> pagingData = this.defaultPersistenceManager.pagingQuery(connection, table,
|
||||
new PagingQuery(1, 1));
|
||||
List<Row> rows = pagingData.getItems();
|
||||
|
||||
assertTrue(rows.size() <= 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Object> 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<Object> 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<Object> 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<Object> setParamValues(Connection cn, PreparedStatement st, List<SqlParamValue> paramValues)
|
||||
throws SQLException
|
||||
{
|
||||
List<Object> 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}的参数值。
|
||||
* <p>
|
||||
* 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Java Types Mapper to
|
||||
* JDBC Types”表。
|
||||
* </p>
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列值。
|
||||
* <p>
|
||||
* 此方法实现参考自JDBC4.0规范“Data Type Conversion Tables”章节中的“Type Conversions
|
||||
* Supported by ResultSet getter Methods”表,并且使用其中的最佳方法。
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
|
@ -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;
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright 2018 datagear.tech. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence;
|
||||
package org.datagear.util;
|
||||
|
||||
/**
|
||||
* SQL参数值。
|
Loading…
Reference in New Issue