com.landawn.abacus.util.JdbcUtil Maven / Gradle / Ivy
/* * Copyright (c) 2015, Haiyang Li. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.landawn.abacus.util; import java.io.InputStream; import java.io.Reader; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.math.BigDecimal; import java.net.URL; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.SQLType; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import com.landawn.abacus.DataSet; import com.landawn.abacus.DirtyMarker; import com.landawn.abacus.EntityId; import com.landawn.abacus.IsolationLevel; import com.landawn.abacus.annotation.Beta; import com.landawn.abacus.annotation.Internal; import com.landawn.abacus.annotation.SequentialOnly; import com.landawn.abacus.annotation.Stateful; import com.landawn.abacus.cache.Cache; import com.landawn.abacus.condition.Condition; import com.landawn.abacus.core.DirtyMarkerUtil; import com.landawn.abacus.core.RowDataSet; import com.landawn.abacus.core.Seid; import com.landawn.abacus.exception.DuplicatedResultException; import com.landawn.abacus.exception.UncheckedSQLException; import com.landawn.abacus.logging.Logger; import com.landawn.abacus.logging.LoggerFactory; import com.landawn.abacus.parser.ParserUtil; import com.landawn.abacus.parser.ParserUtil.EntityInfo; import com.landawn.abacus.parser.ParserUtil.PropInfo; import com.landawn.abacus.type.Type; import com.landawn.abacus.util.Columns.ColumnGetter; import com.landawn.abacus.util.Columns.ColumnOne; import com.landawn.abacus.util.DaoUtil.NonDBOperation; import com.landawn.abacus.util.ExceptionalStream.ExceptionalIterator; import com.landawn.abacus.util.ExceptionalStream.StreamE; import com.landawn.abacus.util.Fn.BiConsumers; import com.landawn.abacus.util.Fn.Suppliers; import com.landawn.abacus.util.NoCachingNoUpdating.DisposableObjArray; import com.landawn.abacus.util.SQLBuilder.SP; import com.landawn.abacus.util.SQLTransaction.CreatedBy; import com.landawn.abacus.util.Tuple.Tuple2; import com.landawn.abacus.util.Tuple.Tuple3; import com.landawn.abacus.util.Tuple.Tuple4; import com.landawn.abacus.util.Tuple.Tuple5; import com.landawn.abacus.util.u.Nullable; import com.landawn.abacus.util.u.Optional; import com.landawn.abacus.util.u.OptionalBoolean; import com.landawn.abacus.util.u.OptionalByte; import com.landawn.abacus.util.u.OptionalChar; import com.landawn.abacus.util.u.OptionalDouble; import com.landawn.abacus.util.u.OptionalFloat; import com.landawn.abacus.util.u.OptionalInt; import com.landawn.abacus.util.u.OptionalLong; import com.landawn.abacus.util.u.OptionalShort; import com.landawn.abacus.util.function.BiConsumer; import com.landawn.abacus.util.function.BinaryOperator; import com.landawn.abacus.util.function.Function; import com.landawn.abacus.util.function.Supplier; import com.landawn.abacus.util.stream.Collector; import com.landawn.abacus.util.stream.EntryStream; import com.landawn.abacus.util.stream.Stream; import com.landawn.abacus.util.stream.Stream.StreamEx; /** * The Class JdbcUtil. * * @author Haiyang Li * @see {@link com.landawn.abacus.condition.ConditionFactory} * @see {@link com.landawn.abacus.condition.ConditionFactory.CF} * @see {@link com.landawn.abacus.annotation.ReadOnly} * @see {@link com.landawn.abacus.annotation.ReadOnlyId} * @see {@link com.landawn.abacus.annotation.NonUpdatable} * @see {@link com.landawn.abacus.annotation.Transient} * @see {@link com.landawn.abacus.annotation.Table} * @see {@link com.landawn.abacus.annotation.Column} * @see http://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html * @see http://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html * @see http://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html * @see http://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html * @since 0.8 */ public final class JdbcUtil { /** The Constant logger. */ static final Logger logger = LoggerFactory.getLogger(JdbcUtil.class); /** The Constant DEFAULT_BATCH_SIZE. */ public static final int DEFAULT_BATCH_SIZE = 200; /** The Constant CURRENT_DIR_PATH. */ // ... static final String CURRENT_DIR_PATH = "./"; /** The async executor. */ static final AsyncExecutor asyncExecutor = new AsyncExecutor(Math.max(8, IOUtil.CPU_CORES), Math.max(64, IOUtil.CPU_CORES), 180L, TimeUnit.SECONDS); /** The Constant DEFAULT_STMT_SETTER. */ static final JdbcUtil.BiParametersSetter super PreparedStatement, ? super Object[]> DEFAULT_STMT_SETTER = new JdbcUtil.BiParametersSetter
* * It's incorrect to use flag to identity the transaction should be committed or rolled back. * Don't write below code: *() { @Override public void accept(PreparedStatement stmt, Object[] parameters) throws SQLException { for (int i = 0, len = parameters.length; i < len; i++) { stmt.setObject(i + 1, parameters[i]); } } }; /** The Constant sqlStateForTableNotExists. */ private static final Set sqlStateForTableNotExists = N.newHashSet(); static { sqlStateForTableNotExists.add("42S02"); // for MySQCF. sqlStateForTableNotExists.add("42P01"); // for PostgreSQCF. sqlStateForTableNotExists.add("42501"); // for HSQLDB. } /** * Instantiates a new jdbc util. */ private JdbcUtil() { // singleton } /** * Creates the DataSource. * * @param url * @param user * @param password * @return */ public static javax.sql.DataSource createHikariDataSource(final String url, final String user, final String password) { try { final com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig(); config.setJdbcUrl(url); config.setUsername(user); config.setPassword(password); return new com.zaxxer.hikari.HikariDataSource(config); } catch (Throwable e) { throw N.toRuntimeException(e); } } /** * Creates the DataSource. * * @param url * @param user * @param password * @return */ public static javax.sql.DataSource createC3p0DataSource(final String url, final String user, final String password) { try { final com.mchange.v2.c3p0.ComboPooledDataSource cpds = new com.mchange.v2.c3p0.ComboPooledDataSource(); cpds.setJdbcUrl(url); cpds.setUser(user); cpds.setPassword(password); return cpds; } catch (Throwable e) { throw N.toRuntimeException(e); } } /** * Creates the connection. * * @param url * @param user * @param password * @return * @throws UncheckedSQLException the unchecked SQL exception */ public static Connection createConnection(final String url, final String user, final String password) throws UncheckedSQLException { return createConnection(getDriverClasssByUrl(url), url, user, password); } /** * Creates the connection. * * @param driverClass * @param url * @param user * @param password * @return * @throws UncheckedSQLException the unchecked SQL exception */ public static Connection createConnection(final String driverClass, final String url, final String user, final String password) throws UncheckedSQLException { final Class extends Driver> cls = ClassUtil.forClass(driverClass); return createConnection(cls, url, user, password); } /** * Creates the connection. * * @param driverClass * @param url * @param user * @param password * @return * @throws UncheckedSQLException the unchecked SQL exception */ public static Connection createConnection(final Class extends Driver> driverClass, final String url, final String user, final String password) throws UncheckedSQLException { try { DriverManager.registerDriver(N.newInstance(driverClass)); return DriverManager.getConnection(url, user, password); } catch (SQLException e) { throw new UncheckedSQLException("Failed to close create connection", e); } } /** * Gets the driver classs by url. * * @param url * @return */ private static Class extends Driver> getDriverClasssByUrl(final String url) { N.checkArgNotNullOrEmpty(url, "url"); Class extends Driver> driverClass = null; // jdbc:mysql://localhost:3306/abacustest if (url.indexOf("mysql") > 0 || StringUtil.indexOfIgnoreCase(url, "mysql") > 0) { driverClass = ClassUtil.forClass("com.mysql.jdbc.Driver"); // jdbc:postgresql://localhost:5432/abacustest } else if (url.indexOf("postgresql") > 0 || StringUtil.indexOfIgnoreCase(url, "postgresql") > 0) { driverClass = ClassUtil.forClass("org.postgresql.Driver"); // jdbc:h2:hsql:// : / } else if (url.indexOf("h2") > 0 || StringUtil.indexOfIgnoreCase(url, "h2") > 0) { driverClass = ClassUtil.forClass("org.h2.Driver"); // jdbc:hsqldb:hsql://localhost/abacustest } else if (url.indexOf("hsqldb") > 0 || StringUtil.indexOfIgnoreCase(url, "hsqldb") > 0) { driverClass = ClassUtil.forClass("org.hsqldb.jdbc.JDBCDriver"); // jdbc.url=jdbc:oracle:thin:@localhost:1521:abacustest } else if (url.indexOf("oracle") > 0 || StringUtil.indexOfIgnoreCase(url, "oracle") > 0) { driverClass = ClassUtil.forClass("oracle.jdbc.driver.OracleDriver"); // jdbc.url=jdbc:sqlserver://localhost:1433;Database=abacustest } else if (url.indexOf("sqlserver") > 0 || StringUtil.indexOfIgnoreCase(url, "sqlserver") > 0) { driverClass = ClassUtil.forClass("com.microsoft.sqlserver.jdbc.SQLServerDriver"); // jdbc:db2://localhost:50000/abacustest } else if (url.indexOf("db2") > 0 || StringUtil.indexOfIgnoreCase(url, "db2") > 0) { driverClass = ClassUtil.forClass("com.ibm.db2.jcc.DB2Driver"); } else { throw new IllegalArgumentException( "Can not identity the driver class by url: " + url + ". Only mysql, postgresql, hsqldb, sqlserver, oracle and db2 are supported currently"); } return driverClass; } /** The is in spring. */ private static boolean isInSpring = true; static { try { isInSpring = ClassUtil.forClass("org.springframework.jdbc.datasource.DataSourceUtils") != null; } catch (Throwable e) { isInSpring = false; } } /** * Spring Transaction is supported and Integrated. * If this method is called where a Spring transaction is started with the specified {@code DataSource}, * the {@code Connection} started the Spring Transaction will be returned. Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be returned. * * @param ds * @return * @throws UncheckedSQLException the unchecked SQL exception */ public static Connection getConnection(final javax.sql.DataSource ds) throws UncheckedSQLException { if (isInSpring && !isSpringTransactionalDisabled_TL.get()) { try { return org.springframework.jdbc.datasource.DataSourceUtils.getConnection(ds); } catch (NoClassDefFoundError e) { isInSpring = false; try { return ds.getConnection(); } catch (SQLException e1) { throw new UncheckedSQLException(e1); } } } else { try { return ds.getConnection(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } } /** * Spring Transaction is supported and Integrated. * If this method is called where a Spring transaction is started with the specified {@code DataSource}, * the specified {@code Connection} won't be returned to {@code DataSource}(Connection pool) until the transaction is committed or rolled back. Otherwise the specified {@code Connection} will be directly returned back to {@code DataSource}(Connection pool). * * @param conn * @param ds */ public static void releaseConnection(final Connection conn, final javax.sql.DataSource ds) { if (conn == null) { return; } if (isInSpring && ds != null && !isSpringTransactionalDisabled_TL.get()) { try { org.springframework.jdbc.datasource.DataSourceUtils.releaseConnection(conn, ds); } catch (NoClassDefFoundError e) { isInSpring = false; JdbcUtil.closeQuietly(conn); } } else { JdbcUtil.closeQuietly(conn); } } /** * Creates the close handler. * * @param conn * @param ds * @return */ static Runnable createCloseHandler(final Connection conn, final javax.sql.DataSource ds) { return () -> releaseConnection(conn, ds); } /** * * @param rs * @throws UncheckedSQLException the unchecked SQL exception */ public static void close(final ResultSet rs) throws UncheckedSQLException { if (rs != null) { try { rs.close(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } } /** * * @param rs * @param closeStatement * @throws UncheckedSQLException the unchecked SQL exception */ public static void close(final ResultSet rs, final boolean closeStatement) throws UncheckedSQLException { close(rs, closeStatement, false); } /** * * @param rs * @param closeStatement * @param closeConnection * @throws IllegalArgumentException if {@code closeStatement = false} while {@code closeConnection = true}. * @throws UncheckedSQLException the unchecked SQL exception */ public static void close(final ResultSet rs, final boolean closeStatement, final boolean closeConnection) throws IllegalArgumentException, UncheckedSQLException { if (closeConnection && closeStatement == false) { throw new IllegalArgumentException("'closeStatement' can't be false while 'closeConnection' is true"); } if (rs == null) { return; } Connection conn = null; Statement stmt = null; try { if (closeStatement || closeConnection) { stmt = rs.getStatement(); } if (closeConnection && stmt != null) { conn = stmt.getConnection(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { close(rs, stmt, conn); } } /** * * @param stmt * @throws UncheckedSQLException the unchecked SQL exception */ public static void close(final Statement stmt) throws UncheckedSQLException { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } } /** * * @param conn * @throws UncheckedSQLException the unchecked SQL exception * @deprecated consider using {@link #releaseConnection(Connection, javax.sql.DataSource)} */ @Deprecated public static void close(final Connection conn) throws UncheckedSQLException { if (conn != null) { try { conn.close(); } catch (SQLException e) { throw new UncheckedSQLException(e); } } } /** * * @param rs * @param stmt * @throws UncheckedSQLException the unchecked SQL exception */ public static void close(final ResultSet rs, final Statement stmt) throws UncheckedSQLException { try { if (rs != null) { rs.close(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { try { if (stmt != null) { stmt.close(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } } } /** * * @param stmt * @param conn * @throws UncheckedSQLException the unchecked SQL exception */ public static void close(final Statement stmt, final Connection conn) throws UncheckedSQLException { try { if (stmt != null) { stmt.close(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { try { if (conn != null) { conn.close(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } } } /** * * @param rs * @param stmt * @param conn * @throws UncheckedSQLException the unchecked SQL exception */ public static void close(final ResultSet rs, final Statement stmt, final Connection conn) throws UncheckedSQLException { try { if (rs != null) { rs.close(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { try { if (stmt != null) { stmt.close(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { try { if (conn != null) { conn.close(); } } catch (SQLException e) { throw new UncheckedSQLException(e); } } } } /** * Unconditionally close an ResultSet
. ** Equivalent to {@link ResultSet#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param rs */ public static void closeQuietly(final ResultSet rs) { closeQuietly(rs, null, null); } /** * * @param rs * @param closeStatement * @throws UncheckedSQLException the unchecked SQL exception */ public static void closeQuietly(final ResultSet rs, final boolean closeStatement) throws UncheckedSQLException { closeQuietly(rs, closeStatement, false); } /** * * @param rs * @param closeStatement * @param closeConnection * @throws IllegalArgumentException if {@code closeStatement = false} while {@code closeConnection = true}. */ public static void closeQuietly(final ResultSet rs, final boolean closeStatement, final boolean closeConnection) throws IllegalArgumentException { if (closeConnection && closeStatement == false) { throw new IllegalArgumentException("'closeStatement' can't be false while 'closeConnection' is true"); } if (rs == null) { return; } Connection conn = null; Statement stmt = null; try { if (closeStatement || closeConnection) { stmt = rs.getStatement(); } if (closeConnection && stmt != null) { conn = stmt.getConnection(); } } catch (SQLException e) { logger.error("Failed to get Statement or Connection by ResultSet", e); } finally { closeQuietly(rs, stmt, conn); } } /** * Unconditionally close an
Statement
. ** Equivalent to {@link Statement#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param stmt */ public static void closeQuietly(final Statement stmt) { closeQuietly(null, stmt, null); } /** * Unconditionally close an
Connection
. ** Equivalent to {@link Connection#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param conn * @deprecated consider using {@link #releaseConnection(Connection, javax.sql.DataSource)} */ @Deprecated public static void closeQuietly(final Connection conn) { closeQuietly(null, null, conn); } /** * Unconditionally close the
ResultSet, Statement
. ** Equivalent to {@link ResultSet#close()}, {@link Statement#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param rs * @param stmt */ public static void closeQuietly(final ResultSet rs, final Statement stmt) { closeQuietly(rs, stmt, null); } /** * Unconditionally close the
Statement, Connection
. ** Equivalent to {@link Statement#close()}, {@link Connection#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param stmt * @param conn */ public static void closeQuietly(final Statement stmt, final Connection conn) { closeQuietly(null, stmt, conn); } /** * Unconditionally close the
ResultSet, Statement, Connection
. ** Equivalent to {@link ResultSet#close()}, {@link Statement#close()}, {@link Connection#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * * @param rs * @param stmt * @param conn */ public static void closeQuietly(final ResultSet rs, final Statement stmt, final Connection conn) { if (rs != null) { try { rs.close(); } catch (Exception e) { logger.error("Failed to close ResultSet", e); } } if (stmt != null) { try { stmt.close(); } catch (Exception e) { logger.error("Failed to close Statement", e); } } if (conn != null) { try { conn.close(); } catch (Exception e) { logger.error("Failed to close Connection", e); } } } /** * * @param rs * @param n the count of row to move ahead. * @return * @throws SQLException the SQL exception */ public static int skip(final ResultSet rs, int n) throws SQLException { return skip(rs, (long) n); } /** * * @param rs * @param n the count of row to move ahead. * @return * @throws SQLException the SQL exception * @see {@link ResultSet#absolute(int)} */ public static int skip(final ResultSet rs, long n) throws SQLException { if (n <= 0) { return 0; } else if (n == 1) { return rs.next() == true ? 1 : 0; } else { final int currentRow = rs.getRow(); if (n <= Integer.MAX_VALUE) { try { if (n > Integer.MAX_VALUE - rs.getRow()) { while (n-- > 0L && rs.next()) { } } else { rs.absolute((int) n + rs.getRow()); } } catch (SQLException e) { while (n-- > 0L && rs.next()) { } } } else { while (n-- > 0L && rs.next()) { } } return rs.getRow() - currentRow; } } /** * Gets the column count. * * @param rs * @return * @throws SQLException the SQL exception */ public static int getColumnCount(ResultSet rs) throws SQLException { return rs.getMetaData().getColumnCount(); } /** * Gets the column name list. * * @param conn * @param tableName * @return * @throws SQLException the SQL exception */ public static List
getColumnNameList(final Connection conn, final String tableName) throws SQLException { final String query = "SELECT * FROM " + tableName + " WHERE 1 > 2"; PreparedStatement stmt = null; ResultSet rs = null; try { stmt = prepareStatement(conn, query); rs = executeQuery(stmt); final ResultSetMetaData metaData = rs.getMetaData(); final int columnCount = metaData.getColumnCount(); final List columnNameList = new ArrayList<>(columnCount); for (int i = 1, n = columnCount + 1; i < n; i++) { columnNameList.add(metaData.getColumnName(i)); } return columnNameList; } finally { closeQuietly(rs, stmt); } } public static List getColumnLabelList(ResultSet rs) throws SQLException { final ResultSetMetaData metaData = rs.getMetaData(); final int columnCount = metaData.getColumnCount(); final List labelList = new ArrayList<>(columnCount); for (int i = 1, n = columnCount + 1; i < n; i++) { labelList.add(getColumnLabel(metaData, i)); } return labelList; } /** * Gets the column label. * * @param rsmd * @param columnIndex * @return * @throws SQLException the SQL exception */ public static String getColumnLabel(final ResultSetMetaData rsmd, final int columnIndex) throws SQLException { final String result = rsmd.getColumnLabel(columnIndex); return N.isNullOrEmpty(result) ? rsmd.getColumnName(columnIndex) : result; } /** * Returns the column index starts with from 1, not 0. * * @param resultSet * @param columnName * @return * @throws UncheckedSQLException the unchecked SQL exception */ public static int getColumnIndex(final ResultSet resultSet, final String columnName) throws UncheckedSQLException { try { return getColumnIndex(resultSet.getMetaData(), columnName); } catch (SQLException e) { throw new UncheckedSQLException(e); } } /** * Returns the column index starts with from 1, not 0. * * @param rsmd * @param columnName * @return * @throws SQLException */ public static int getColumnIndex(final ResultSetMetaData rsmd, final String columnName) throws SQLException { final int columnCount = rsmd.getColumnCount(); for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) { if (getColumnLabel(rsmd, columnIndex).equalsIgnoreCase(columnName)) { return columnIndex; } } return -1; } /** * Gets the column value. * * @param rs * @param columnIndex starts with 1, not 0. * @return * @throws SQLException the SQL exception */ public static Object getColumnValue(final ResultSet rs, final int columnIndex) throws SQLException { // Copied from JdbcUtils#getResultSetValue(ResultSet, int) in SpringJdbc under Apache License, Version 2.0. Object obj = rs.getObject(columnIndex); if (obj == null || obj instanceof String || obj instanceof Number) { return obj; } final String className = obj.getClass().getName(); if (obj instanceof Blob) { Blob blob = (Blob) obj; obj = blob.getBytes(1, (int) blob.length()); } else if (obj instanceof Clob) { Clob clob = (Clob) obj; obj = clob.getSubString(1, (int) clob.length()); } else if ("oracle.sql.TIMESTAMP".equals(className) || "oracle.sql.TIMESTAMPTZ".equals(className)) { obj = rs.getTimestamp(columnIndex); } else if (className != null && className.startsWith("oracle.sql.DATE")) { final String metaDataClassName = rs.getMetaData().getColumnClassName(columnIndex); if ("java.sql.Timestamp".equals(metaDataClassName) || "oracle.sql.TIMESTAMP".equals(metaDataClassName)) { obj = rs.getTimestamp(columnIndex); } else { obj = rs.getDate(columnIndex); } } else if (obj instanceof java.sql.Date) { if ("java.sql.Timestamp".equals(rs.getMetaData().getColumnClassName(columnIndex))) { obj = rs.getTimestamp(columnIndex); } } return obj; } /** * Gets the column value. * * @param rs * @param columnLabel * @return * @throws SQLException the SQL exception * @deprecated please consider using {@link #getColumnValue(ResultSet, int)} */ @Deprecated public static Object getColumnValue(final ResultSet rs, final String columnLabel) throws SQLException { // Copied from JdbcUtils#getResultSetValue(ResultSet, int) in SpringJdbc under Apache License, Version 2.0. Object obj = rs.getObject(columnLabel); if (obj == null || obj instanceof String || obj instanceof Number) { return obj; } final String className = obj.getClass().getName(); if (obj instanceof Blob) { Blob blob = (Blob) obj; obj = blob.getBytes(1, (int) blob.length()); } else if (obj instanceof Clob) { Clob clob = (Clob) obj; obj = clob.getSubString(1, (int) clob.length()); } else if ("oracle.sql.TIMESTAMP".equals(className) || "oracle.sql.TIMESTAMPTZ".equals(className)) { obj = rs.getTimestamp(columnLabel); } else { final ResultSetMetaData metaData = rs.getMetaData(); final int columnIndex = getColumnIndex(metaData, columnLabel); if (className != null && className.startsWith("oracle.sql.DATE")) { final String metaDataClassName = metaData.getColumnClassName(columnIndex); if ("java.sql.Timestamp".equals(metaDataClassName) || "oracle.sql.TIMESTAMP".equals(metaDataClassName)) { obj = rs.getTimestamp(columnLabel); } else { obj = rs.getDate(columnLabel); } } else if (obj instanceof java.sql.Date) { if ("java.sql.Timestamp".equals(metaData.getColumnClassName(columnIndex))) { obj = rs.getTimestamp(columnLabel); } } } return obj; } /** * Gets the column value. * * @param * @param targetClass * @param rs * @param columnIndex * @return * @throws SQLException the SQL exception */ public static T getColumnValue(final Class targetClass, final ResultSet rs, final int columnIndex) throws SQLException { return N. typeOf(targetClass).get(rs, columnIndex); } /** * Gets the column value. * * @param * @param targetClass * @param rs * @param columnLabel * @return * @throws SQLException the SQL exception * @deprecated please consider using {@link #getColumnValue(Class, ResultSet, int)} */ @Deprecated public static T getColumnValue(final Class targetClass, final ResultSet rs, final String columnLabel) throws SQLException { return N. typeOf(targetClass).get(rs, columnLabel); } // /** The Constant column2FieldNameMapPool. */ // private static final Map , ImmutableMap > column2FieldNameMapPool = new ConcurrentHashMap<>(); // // /** // * Gets the column 2 field name map. // * // * @param entityClass // * @return // */ // static ImmutableMap getColumn2FieldNameMap(Class> entityClass) { // ImmutableMap result = column2FieldNameMapPool.get(entityClass); // // if (result == null) { // final Map map = new HashMap<>(); // final EntityInfo entityInfo = ParserUtil.getEntityInfo(entityClass); // // for (PropInfo propInfo : entityInfo.propInfoList) { // if (propInfo.columnName.isPresent()) { // map.put(propInfo.columnName.get(), propInfo.name); // map.put(propInfo.columnName.get().toLowerCase(), propInfo.name); // map.put(propInfo.columnName.get().toUpperCase(), propInfo.name); // } // } // // result = ImmutableMap.copyOf(map); // // column2FieldNameMapPool.put(entityClass, result); // } // // return result; // } public static ImmutableMap getColumn2FieldNameMap(Class> entityClass) { return ClassUtil.getColumn2FieldNameMap(entityClass); } /** * * @param ds * @return */ public static boolean isInTransaction(final javax.sql.DataSource ds) { if (SQLTransaction.getTransaction(ds, CreatedBy.JDBC_UTIL) != null) { return true; } if (isInSpring && !isSpringTransactionalDisabled_TL.get()) { Connection conn = null; try { conn = getConnection(ds); return org.springframework.jdbc.datasource.DataSourceUtils.isConnectionTransactional(conn, ds); } catch (NoClassDefFoundError e) { isInSpring = false; } finally { releaseConnection(conn, ds); } } return false; } /** * Refer to: {@code beginTransaction(javax.sql.DataSource, IsolationLevel, boolean)}. * * @param dataSource * @return * @throws UncheckedSQLException the unchecked SQL exception * @see {@link #beginTransaction(javax.sql.DataSource, IsolationLevel, boolean)} */ public static SQLTransaction beginTransaction(final javax.sql.DataSource dataSource) throws UncheckedSQLException { return beginTransaction(dataSource, IsolationLevel.DEFAULT); } /** * Refer to: {@code beginTransaction(javax.sql.DataSource, IsolationLevel, boolean)}. * * @param dataSource * @param isolationLevel * @return * @throws UncheckedSQLException the unchecked SQL exception * @see {@link #beginTransaction(javax.sql.DataSource, IsolationLevel, boolean)} */ public static SQLTransaction beginTransaction(final javax.sql.DataSource dataSource, final IsolationLevel isolationLevel) throws UncheckedSQLException { return beginTransaction(dataSource, isolationLevel, false); } /** * Starts a global transaction which will be shared by all in-line database query with the same {@code DataSource} in the same thread, * including methods: {@code JdbcUtil.beginTransaction/prepareQuery/prepareNamedQuery/prepareCallableQuery, SQLExecutor(Mapper).beginTransaction/get/insert/batchInsert/update/batchUpdate/query/list/findFirst/...} * *
* Spring Transaction is supported and Integrated. * If this method is called at where a Spring transaction is started with the specified {@code DataSource}, * the {@code Connection} started the Spring Transaction will be used here. * That's to say the Spring transaction will have the final control on commit/roll back over the {@code Connection}. * *
*
* * Here is the general code pattern to work with {@code SQLTransaction}. * **** public void doSomethingA() { * ... * final SQLTransaction tranA = JdbcUtil.beginTransaction(dataSource1, isolation); * * try { * ... * doSomethingB(); // Share the same transaction 'tranA' because they're in the same thread and start transaction with same DataSource 'dataSource1'. * ... * doSomethingC(); // won't share the same transaction 'tranA' although they're in the same thread but start transaction with different DataSource 'dataSource2'. * ... * tranA.commit(); * } finally { * tranA.rollbackIfNotCommitted(); * } * } * * public void doSomethingB() { * ... * final SQLTransaction tranB = JdbcUtil.beginTransaction(dataSource1, isolation); * try { * // do your work with the conn... * ... * tranB.commit(); * } finally { * tranB.rollbackIfNotCommitted(); * } * } * * public void doSomethingC() { * ... * final SQLTransaction tranC = JdbcUtil.beginTransaction(dataSource2, isolation); * try { * // do your work with the conn... * ... * tranC.commit(); * } finally { * tranC.rollbackIfNotCommitted(); * } * } *
** * @param dataSource * @param isolationLevel * @param isForUpdateOnly * @return * @throws UncheckedSQLException the unchecked SQL exception * @see {@link #getConnection(javax.sql.DataSource)} * @see {@link #releaseConnection(Connection, javax.sql.DataSource)} * @see SQLExecutor#beginTransaction(IsolationLevel, boolean, JdbcSettings) */ public static SQLTransaction beginTransaction(final javax.sql.DataSource dataSource, final IsolationLevel isolationLevel, final boolean isForUpdateOnly) throws UncheckedSQLException { N.checkArgNotNull(dataSource, "dataSource"); N.checkArgNotNull(isolationLevel, "isolationLevel"); SQLTransaction tran = SQLTransaction.getTransaction(dataSource, CreatedBy.JDBC_UTIL); if (tran == null) { Connection conn = null; boolean noException = false; try { conn = getConnection(dataSource); tran = new SQLTransaction(dataSource, conn, isolationLevel, CreatedBy.JDBC_UTIL, true); tran.incrementAndGetRef(isolationLevel, isForUpdateOnly); noException = true; } catch (SQLException e) { throw new UncheckedSQLException(e); } finally { if (noException == false) { releaseConnection(conn, dataSource); } } logger.info("Create a new SQLTransaction(id={})", tran.id()); SQLTransaction.putTransaction(tran); } else { logger.info("Reusing the existing SQLTransaction(id={})", tran.id()); tran.incrementAndGetRef(isolationLevel, isForUpdateOnly); } return tran; } /** * * @param* public void doSomethingA() { * ... * final SQLTransaction tranA = JdbcUtil.beginTransaction(dataSource1, isolation); * boolean flagToCommit = false; * try { * // do your work with the conn... * ... * flagToCommit = true; * } finally { * if (flagToCommit) { * tranA.commit(); * } else { * tranA.rollbackIfNotCommitted(); * } * } * } *
** @param * @param ds * @param cmd * @return * @throws E */ @Beta public static T callInTransaction(final javax.sql.DataSource ds, final Throwables.Callable cmd) throws E { final SQLTransaction tran = JdbcUtil.beginTransaction(ds); T result = null; try { result = cmd.call(); tran.commit(); } finally { tran.rollbackIfNotCommitted(); } return result; } /** * * @param * @param * @param ds * @param cmd * @return * @throws E */ @Beta public static T callInTransaction(final javax.sql.DataSource ds, final Throwables.Function cmd) throws E { final SQLTransaction tran = JdbcUtil.beginTransaction(ds); T result = null; try { result = cmd.apply(ds); tran.commit(); } finally { tran.rollbackIfNotCommitted(); } return result; } /** * * @param * @param ds * @param cmd * @return * @throws E */ @Beta public static void runInTransaction(final javax.sql.DataSource ds, final Throwables.Runnable cmd) throws E { final SQLTransaction tran = JdbcUtil.beginTransaction(ds); try { cmd.run(); tran.commit(); } finally { tran.rollbackIfNotCommitted(); } } /** * * @param * @param ds * @param cmd * @return * @throws E */ @Beta public static void runInTransaction(final javax.sql.DataSource ds, final Throwables.Consumer cmd) throws E { final SQLTransaction tran = JdbcUtil.beginTransaction(ds); try { cmd.accept(ds); tran.commit(); } finally { tran.rollbackIfNotCommitted(); } } /** * * @param * @param * @param ds * @param cmd * @return * @throws E */ @Beta public static T callNotInStartedTransaction(final javax.sql.DataSource ds, final Throwables.Callable cmd) throws E { final SQLTransaction tran = SQLTransaction.getTransaction(ds, CreatedBy.JDBC_UTIL); if (isInSpring && !isSpringTransactionalDisabled_TL.get()) { JdbcUtil.disableSpringTransactional(true); try { if (tran == null) { return cmd.call(); } else { return tran.callNotInMe(cmd); } } finally { JdbcUtil.disableSpringTransactional(false); } } else { if (tran == null) { return cmd.call(); } else { return tran.callNotInMe(cmd); } } } /** * * @param * @param * @param ds * @param cmd * @return * @throws E */ @Beta public static T callNotInStartedTransaction(final javax.sql.DataSource ds, final Throwables.Function cmd) throws E { final SQLTransaction tran = SQLTransaction.getTransaction(ds, CreatedBy.JDBC_UTIL); if (isInSpring && !isSpringTransactionalDisabled_TL.get()) { JdbcUtil.disableSpringTransactional(true); try { if (tran == null) { return cmd.apply(ds); } else { return tran.callNotInMe(() -> cmd.apply(ds)); } } finally { JdbcUtil.disableSpringTransactional(false); } } else { if (tran == null) { return cmd.apply(ds); } else { return tran.callNotInMe(() -> cmd.apply(ds)); } } } /** * * @param * @param ds * @param cmd * @return * @throws E */ @Beta public static void runNotInStartedTransaction(final javax.sql.DataSource ds, final Throwables.Runnable cmd) throws E { final SQLTransaction tran = SQLTransaction.getTransaction(ds, CreatedBy.JDBC_UTIL); if (isInSpring && !isSpringTransactionalDisabled_TL.get()) { JdbcUtil.disableSpringTransactional(true); try { if (tran == null) { cmd.run(); } else { tran.runNotInMe(cmd); } } finally { JdbcUtil.disableSpringTransactional(false); } } else { if (tran == null) { cmd.run(); } else { tran.runNotInMe(cmd); } } } /** * * @param * @param ds * @param cmd * @return * @throws E */ @Beta public static void runNotInStartedTransaction(final javax.sql.DataSource ds, final Throwables.Consumer cmd) throws E { final SQLTransaction tran = SQLTransaction.getTransaction(ds, CreatedBy.JDBC_UTIL); if (isInSpring && !isSpringTransactionalDisabled_TL.get()) { JdbcUtil.disableSpringTransactional(true); try { if (tran == null) { cmd.accept(ds); } else { tran.runNotInMe(() -> cmd.accept(ds)); } } finally { JdbcUtil.disableSpringTransactional(false); } } else { if (tran == null) { cmd.accept(ds); } else { tran.runNotInMe(() -> cmd.accept(ds)); } } } /** * Gets the SQL operation. * * @param sql * @return */ static SQLOperation getSQLOperation(String sql) { if (StringUtil.startsWithIgnoreCase(sql.trim(), "select ")) { return SQLOperation.SELECT; } else if (StringUtil.startsWithIgnoreCase(sql.trim(), "update ")) { return SQLOperation.UPDATE; } else if (StringUtil.startsWithIgnoreCase(sql.trim(), "insert ")) { return SQLOperation.INSERT; } else if (StringUtil.startsWithIgnoreCase(sql.trim(), "delete ")) { return SQLOperation.DELETE; } else { for (SQLOperation so : SQLOperation.values()) { if (StringUtil.startsWithIgnoreCase(sql.trim(), so.name())) { return so; } } } return SQLOperation.UNKNOWN; } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param sql * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static PreparedQuery prepareQuery(final javax.sql.DataSource ds, final String sql) throws SQLException { final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareQuery(tran.connection(), sql); } else { PreparedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareQuery(conn, sql).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param sql * @param autoGeneratedKeys * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static PreparedQuery prepareQuery(final javax.sql.DataSource ds, final String sql, final boolean autoGeneratedKeys) throws SQLException { final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareQuery(tran.connection(), sql, autoGeneratedKeys); } else { PreparedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareQuery(conn, sql, autoGeneratedKeys).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * * @param ds * @param sql * @param returnColumnIndexes * @return * @throws SQLException the SQL exception */ public static PreparedQuery prepareQuery(final javax.sql.DataSource ds, final String sql, final int[] returnColumnIndexes) throws SQLException { final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareQuery(tran.connection(), sql, returnColumnIndexes); } else { PreparedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareQuery(conn, sql, returnColumnIndexes).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * * @param ds * @param sql * @param returnColumnNames * @return * @throws SQLException the SQL exception */ public static PreparedQuery prepareQuery(final javax.sql.DataSource ds, final String sql, final String[] returnColumnNames) throws SQLException { final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareQuery(tran.connection(), sql, returnColumnNames); } else { PreparedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareQuery(conn, sql, returnColumnNames).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param sql * @param stmtCreator the created {@code PreparedStatement} will be closed after any execution methods in {@code PreparedQuery/PreparedCallableQuery} is called. * An execution method is a method which will trigger the backed {@code PreparedStatement/CallableStatement} to be executed, for example: get/query/queryForInt/Long/../findFirst/list/execute/.... * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static PreparedQuery prepareQuery(final javax.sql.DataSource ds, final String sql, final Throwables.BiFunction stmtCreator) throws SQLException { final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareQuery(tran.connection(), sql, stmtCreator); } else { PreparedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareQuery(conn, sql, stmtCreator).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * Never write below code because it will definitely cause {@code Connection} leak: * ** * @param conn the specified {@code conn} won't be close after this query is executed. * @param sql * @return * @throws SQLException the SQL exception */ public static PreparedQuery prepareQuery(final Connection conn, final String sql) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); return new PreparedQuery(prepareStatement(conn, sql)); } /** * * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareQuery(dataSource.getConnection(), sql); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param sql * @param autoGeneratedKeys * @return * @throws SQLException the SQL exception */ public static PreparedQuery prepareQuery(final Connection conn, final String sql, final boolean autoGeneratedKeys) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); return new PreparedQuery(prepareStatement(conn, sql, autoGeneratedKeys)); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareQuery(dataSource.getConnection(), sql, autoGeneratedKeys); *
*** * @param conn * @param sql * @param returnColumnIndexes * @return * @throws SQLException the SQL exception */ public static PreparedQuery prepareQuery(final Connection conn, final String sql, final int[] returnColumnIndexes) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); N.checkArgNotNullOrEmpty(returnColumnIndexes, "returnColumnIndexes"); return new PreparedQuery(prepareStatement(conn, sql, returnColumnIndexes)); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareQuery(dataSource.getConnection(), sql, returnColumnIndexes); *
*** * @param conn * @param sql * @param returnColumnNames * @return * @throws SQLException the SQL exception */ public static PreparedQuery prepareQuery(final Connection conn, final String sql, final String[] returnColumnNames) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); N.checkArgNotNullOrEmpty(returnColumnNames, "returnColumnNames"); return new PreparedQuery(prepareStatement(conn, sql, returnColumnNames)); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareQuery(dataSource.getConnection(), sql, returnColumnNames); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param sql * @param stmtCreator the created {@code PreparedStatement} will be closed after any execution methods in {@code PreparedQuery/PreparedCallableQuery} is called. * An execution method is a method which will trigger the backed {@code PreparedStatement/CallableStatement} to be executed, for example: get/query/queryForInt/Long/../findFirst/list/execute/.... * @return * @throws SQLException the SQL exception */ public static PreparedQuery prepareQuery(final Connection conn, final String sql, final Throwables.BiFunction* JdbcUtil.prepareQuery(dataSource.getConnection(), sql, stmtCreator); *
*stmtCreator) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); N.checkArgNotNull(stmtCreator, "stmtCreator"); return new PreparedQuery(prepareStatement(conn, sql, stmtCreator)); } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final String namedSql) throws SQLException { final SQLTransaction tran = getTransaction(ds, namedSql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param autoGeneratedKeys * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final String namedSql, final boolean autoGeneratedKeys) throws SQLException { final SQLTransaction tran = getTransaction(ds, namedSql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql, autoGeneratedKeys); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql, autoGeneratedKeys).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param returnColumnIndexes * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final String namedSql, final int[] returnColumnIndexes) throws SQLException { final SQLTransaction tran = getTransaction(ds, namedSql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql, returnColumnIndexes); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql, returnColumnIndexes).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param returnColumnNames * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final String namedSql, final String[] returnColumnNames) throws SQLException { final SQLTransaction tran = getTransaction(ds, namedSql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql, returnColumnNames); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql, returnColumnNames).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param stmtCreator the created {@code PreparedStatement} will be closed after any execution methods in {@code NamedQuery/PreparedCallableQuery} is called. * An execution method is a method which will trigger the backed {@code PreparedStatement/CallableStatement} to be executed, for example: get/query/queryForInt/Long/../findFirst/list/execute/.... * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final String namedSql, final Throwables.BiFunction stmtCreator) throws SQLException { final SQLTransaction tran = getTransaction(ds, namedSql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql, stmtCreator); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql, stmtCreator).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * Never write below code because it will definitely cause {@code Connection} leak: * ** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final String namedSql) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); final ParsedSql parsedSql = parseNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, parsedSql), parsedSql); } /** * * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param autoGeneratedKeys * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final String namedSql, final boolean autoGeneratedKeys) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); final ParsedSql parsedSql = parseNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, parsedSql, autoGeneratedKeys), parsedSql); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql, autoGeneratedKeys); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param returnColumnIndexes * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final String namedSql, final int[] returnColumnIndexes) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); N.checkArgNotNullOrEmpty(returnColumnIndexes, "returnColumnIndexes"); final ParsedSql parsedSql = parseNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, parsedSql, returnColumnIndexes), parsedSql); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param returnColumnNames * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final String namedSql, final String[] returnColumnNames) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); N.checkArgNotNullOrEmpty(returnColumnNames, "returnColumnNames"); final ParsedSql parsedSql = parseNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, parsedSql, returnColumnNames), parsedSql); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param stmtCreator the created {@code PreparedStatement} will be closed after any execution methods in {@code NamedQuery/PreparedCallableQuery} is called. * An execution method is a method which will trigger the backed {@code PreparedStatement/CallableStatement} to be executed, for example: get/query/queryForInt/Long/../findFirst/list/execute/.... * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final String namedSql, final Throwables.BiFunction* JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql, stmtCreator); *
*stmtCreator) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); N.checkArgNotNull(stmtCreator, "stmtCreator"); final ParsedSql parsedSql = parseNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, parsedSql, stmtCreator), parsedSql); } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final ParsedSql namedSql) throws SQLException { validateNamedSql(namedSql); final SQLTransaction tran = getTransaction(ds, namedSql.getParameterizedSql(), CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param autoGeneratedKeys * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final ParsedSql namedSql, final boolean autoGeneratedKeys) throws SQLException { validateNamedSql(namedSql); final SQLTransaction tran = getTransaction(ds, namedSql.getParameterizedSql(), CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql, autoGeneratedKeys); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql, autoGeneratedKeys).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param returnColumnIndexes * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final ParsedSql namedSql, final int[] returnColumnIndexes) throws SQLException { validateNamedSql(namedSql); final SQLTransaction tran = getTransaction(ds, namedSql.getParameterizedSql(), CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql, returnColumnIndexes); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql, returnColumnIndexes).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param returnColumnNames * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final ParsedSql namedSql, final String[] returnColumnNames) throws SQLException { validateNamedSql(namedSql); final SQLTransaction tran = getTransaction(ds, namedSql.getParameterizedSql(), CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql, returnColumnNames); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql, returnColumnNames).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param stmtCreator the created {@code PreparedStatement} will be closed after any execution methods in {@code NamedQuery/PreparedCallableQuery} is called. * An execution method is a method which will trigger the backed {@code PreparedStatement/CallableStatement} to be executed, for example: get/query/queryForInt/Long/../findFirst/list/execute/.... * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static NamedQuery prepareNamedQuery(final javax.sql.DataSource ds, final ParsedSql namedSql, final Throwables.BiFunction stmtCreator) throws SQLException { validateNamedSql(namedSql); final SQLTransaction tran = getTransaction(ds, namedSql.getParameterizedSql(), CreatedBy.JDBC_UTIL); if (tran != null) { return prepareNamedQuery(tran.connection(), namedSql, stmtCreator); } else { NamedQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareNamedQuery(conn, namedSql, stmtCreator).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * Never write below code because it will definitely cause {@code Connection} leak: * ** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final ParsedSql namedSql) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); validateNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, namedSql), namedSql); } /** * * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param autoGeneratedKeys * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final ParsedSql namedSql, final boolean autoGeneratedKeys) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); validateNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, namedSql, autoGeneratedKeys), namedSql); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql, autoGeneratedKeys); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param returnColumnIndexes * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final ParsedSql namedSql, final int[] returnColumnIndexes) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); N.checkArgNotNullOrEmpty(returnColumnIndexes, "returnColumnIndexes"); validateNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, namedSql, returnColumnIndexes), namedSql); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param returnColumnNames * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final ParsedSql namedSql, final String[] returnColumnNames) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); N.checkArgNotNullOrEmpty(returnColumnNames, "returnColumnNames"); validateNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, namedSql, returnColumnNames), namedSql); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param namedSql for example {@code SELECT first_name, last_name FROM account where id = :id} * @param stmtCreator the created {@code PreparedStatement} will be closed after any execution methods in {@code NamedQuery/PreparedCallableQuery} is called. * An execution method is a method which will trigger the backed {@code PreparedStatement/CallableStatement} to be executed, for example: get/query/queryForInt/Long/../findFirst/list/execute/.... * @return * @throws SQLException the SQL exception */ public static NamedQuery prepareNamedQuery(final Connection conn, final ParsedSql namedSql, final Throwables.BiFunction* JdbcUtil.prepareNamedQuery(dataSource.getConnection(), namedSql, stmtCreator); *
*stmtCreator) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(namedSql, "namedSql"); N.checkArgNotNull(stmtCreator, "stmtCreator"); validateNamedSql(namedSql); return new NamedQuery(prepareStatement(conn, namedSql, stmtCreator), namedSql); } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param sql * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static PreparedCallableQuery prepareCallableQuery(final javax.sql.DataSource ds, final String sql) throws SQLException { final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareCallableQuery(tran.connection(), sql); } else { PreparedCallableQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareCallableQuery(conn, sql).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * If this method is called where a transaction is started by {@code JdbcUtil.beginTransaction} or in {@code Spring} with the same {@code DataSource} in the same thread, * the {@code Connection} started the Transaction will be used here. * Otherwise a {@code Connection} directly from the specified {@code DataSource}(Connection pool) will be borrowed and used. * * @param ds * @param sql * @param stmtCreator the created {@code CallableStatement} will be closed after any execution methods in {@code PreparedQuery/PreparedCallableQuery} is called. * An execution method is a method which will trigger the backed {@code PreparedStatement/CallableStatement} to be executed, for example: get/query/queryForInt/Long/../findFirst/list/execute/.... * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static PreparedCallableQuery prepareCallableQuery(final javax.sql.DataSource ds, final String sql, final Throwables.BiFunction stmtCreator) throws SQLException { final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return prepareCallableQuery(tran.connection(), sql, stmtCreator); } else { PreparedCallableQuery result = null; Connection conn = null; try { conn = getConnection(ds); result = prepareCallableQuery(conn, sql, stmtCreator).onClose(createCloseHandler(conn, ds)); } finally { if (result == null) { releaseConnection(conn, ds); } } return result; } } /** * Never write below code because it will definitely cause {@code Connection} leak: * ** * @param conn the specified {@code conn} won't be close after this query is executed. * @param sql * @return * @throws SQLException the SQL exception * @see #getConnection(javax.sql.DataSource) * @see #releaseConnection(Connection, javax.sql.DataSource) */ public static PreparedCallableQuery prepareCallableQuery(final Connection conn, final String sql) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); return new PreparedCallableQuery(prepareCallable(conn, sql)); } /** * Never write below code because it will definitely cause {@code Connection} leak: ** JdbcUtil.prepareCallableQuery(dataSource.getConnection(), sql); *
*** * @param conn the specified {@code conn} won't be close after this query is executed. * @param sql * @param stmtCreator the created {@code CallableStatement} will be closed after any execution methods in {@code PreparedQuery/PreparedCallableQuery} is called. * An execution method is a method which will trigger the backed {@code PreparedStatement/CallableStatement} to be executed, for example: get/query/queryForInt/Long/../findFirst/list/execute/.... * @return * @throws SQLException the SQL exception */ public static PreparedCallableQuery prepareCallableQuery(final Connection conn, final String sql, final Throwables.BiFunction* JdbcUtil.prepareCallableQuery(dataSource.getConnection(), sql, stmtCreator); *
*stmtCreator) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); N.checkArgNotNull(stmtCreator, "stmtCreator"); return new PreparedCallableQuery(prepareCallable(conn, sql, stmtCreator)); } static PreparedStatement prepareStatement(final Connection conn, final String sql) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + sql); } return conn.prepareStatement(sql); } static PreparedStatement prepareStatement(final Connection conn, final String sql, final boolean autoGeneratedKeys) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + sql); } return conn.prepareStatement(sql, autoGeneratedKeys ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS); } static PreparedStatement prepareStatement(final Connection conn, final String sql, final int[] returnColumnIndexes) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + sql); } return conn.prepareStatement(sql, returnColumnIndexes); } static PreparedStatement prepareStatement(final Connection conn, final String sql, final String[] returnColumnNames) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + sql); } return conn.prepareStatement(sql, returnColumnNames); } static PreparedStatement prepareStatement(final Connection conn, final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + sql); } return conn.prepareStatement(sql, resultSetType, resultSetConcurrency); } static PreparedStatement prepareStatement(final Connection conn, final String sql, final Throwables.BiFunction stmtCreator) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + sql); } return stmtCreator.apply(conn, sql); } static PreparedStatement prepareStatement(final Connection conn, final ParsedSql parsedSql) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + parsedSql.sql()); } return conn.prepareStatement(parsedSql.getParameterizedSql()); } static PreparedStatement prepareStatement(final Connection conn, final ParsedSql parsedSql, final boolean autoGeneratedKeys) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + parsedSql.sql()); } return conn.prepareStatement(parsedSql.getParameterizedSql(), autoGeneratedKeys ? Statement.RETURN_GENERATED_KEYS : Statement.NO_GENERATED_KEYS); } static PreparedStatement prepareStatement(final Connection conn, final ParsedSql parsedSql, final int[] returnColumnIndexes) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + parsedSql.sql()); } return conn.prepareStatement(parsedSql.getParameterizedSql(), returnColumnIndexes); } static PreparedStatement prepareStatement(final Connection conn, final ParsedSql parsedSql, final String[] returnColumnNames) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + parsedSql.sql()); } return conn.prepareStatement(parsedSql.getParameterizedSql(), returnColumnNames); } static PreparedStatement prepareStatement(final Connection conn, final ParsedSql parsedSql, final int resultSetType, final int resultSetConcurrency) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + parsedSql.sql()); } return conn.prepareStatement(parsedSql.getParameterizedSql(), resultSetType, resultSetConcurrency); } static PreparedStatement prepareStatement(final Connection conn, final ParsedSql parsedSql, final Throwables.BiFunction stmtCreator) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + parsedSql.sql()); } return stmtCreator.apply(conn, parsedSql.getParameterizedSql()); } static CallableStatement prepareCallable(final Connection conn, final String sql) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + sql); } return conn.prepareCall(sql); } static CallableStatement prepareCallable(final Connection conn, final String sql, final Throwables.BiFunction stmtCreator) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + sql); } return stmtCreator.apply(conn, sql); } static CallableStatement prepareCallable(final Connection conn, final ParsedSql parsedSql) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + parsedSql.sql()); } return conn.prepareCall(parsedSql.getParameterizedSql()); } static CallableStatement prepareCallable(final Connection conn, final ParsedSql parsedSql, final Throwables.BiFunction stmtCreator) throws SQLException { if (isSQLLogEnabled_TL.get()) { logger.info("[SQL]: " + parsedSql.sql()); } return stmtCreator.apply(conn, parsedSql.getParameterizedSql()); } /** * * @param conn * @param sql * @param parameters * @return * @throws SQLException the SQL exception */ @SafeVarargs static PreparedStatement prepareStmt(final Connection conn, final String sql, final Object... parameters) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); final ParsedSql parsedSql = ParsedSql.parse(sql); final PreparedStatement stmt = prepareStatement(conn, parsedSql); if (N.notNullOrEmpty(parameters)) { setParameters(parsedSql, stmt, parameters); } return stmt; } /** * * @param conn * @param sql * @param parameters * @return * @throws SQLException the SQL exception */ @SafeVarargs static CallableStatement prepareCall(final Connection conn, final String sql, final Object... parameters) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); final ParsedSql parsedSql = ParsedSql.parse(sql); final CallableStatement stmt = prepareCallable(conn, parsedSql); if (N.notNullOrEmpty(parameters)) { setParameters(parsedSql, stmt, parameters); } return stmt; } /** * Batch prepare statement. * * @param conn * @param sql * @param parametersList * @return * @throws SQLException the SQL exception */ static PreparedStatement prepareBatchStmt(final Connection conn, final String sql, final List> parametersList) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); final ParsedSql parsedSql = ParsedSql.parse(sql); final PreparedStatement stmt = prepareStatement(conn, parsedSql); for (Object parameters : parametersList) { setParameters(parsedSql, stmt, N.asArray(parameters)); stmt.addBatch(); } return stmt; } /** * * @param conn * @param sql * @param parametersList * @return * @throws SQLException the SQL exception */ static CallableStatement prepareBatchCall(final Connection conn, final String sql, final List> parametersList) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); final ParsedSql parsedSql = ParsedSql.parse(sql); final CallableStatement stmt = prepareCallable(conn, parsedSql); for (Object parameters : parametersList) { setParameters(parsedSql, stmt, N.asArray(parameters)); stmt.addBatch(); } return stmt; } /** * Creates the named SQL. * * @param namedSql * @return */ private static ParsedSql parseNamedSql(final String namedSql) { N.checkArgNotNullOrEmpty(namedSql, "namedSql"); final ParsedSql parsedSql = ParsedSql.parse(namedSql); validateNamedSql(parsedSql); return parsedSql; } private static void validateNamedSql(final ParsedSql namedSql) { if (namedSql.getNamedParameters().size() != namedSql.getParameterCount()) { throw new IllegalArgumentException("\"" + namedSql.sql() + "\" is not a valid named sql:"); } } private static SQLTransaction getTransaction(final javax.sql.DataSource ds, final String sql, final CreatedBy createdBy) { final SQLOperation sqlOperation = JdbcUtil.getSQLOperation(sql); final SQLTransaction tran = SQLTransaction.getTransaction(ds, createdBy); if (tran == null || (tran.isForUpdateOnly() && sqlOperation == SQLOperation.SELECT)) { return null; } else { return tran; } } /** * * @param ds * @param sql * @param parameters * @return * @throws SQLException the SQL exception */ @SafeVarargs public static DataSet executeQuery(final javax.sql.DataSource ds, final String sql, final Object... parameters) throws SQLException { N.checkArgNotNull(ds, "ds"); N.checkArgNotNull(sql, "sql"); final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return executeQuery(tran.connection(), sql, parameters); } else { final Connection conn = getConnection(ds); try { return executeQuery(conn, sql, parameters); } finally { releaseConnection(conn, ds); } } } /** * * @param conn * @param sql * @param parameters * @return * @throws SQLException the SQL exception */ @SafeVarargs public static DataSet executeQuery(final Connection conn, final String sql, final Object... parameters) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); PreparedStatement stmt = null; ResultSet rs = null; try { stmt = prepareStmt(conn, sql, parameters); stmt.setFetchDirection(ResultSet.FETCH_FORWARD); rs = executeQuery(stmt); return extractData(rs); } finally { closeQuietly(rs, stmt); } } // /** // * // * @param stmt // * @return // * @throws SQLException the SQL exception // */ // public static DataSet executeQuery(final PreparedStatement stmt) throws SQLException { // ResultSet rs = null; // // try { // rs = executeQuerry(stmt); // // return extractData(rs); // } finally { // closeQuietly(rs); // } // } /** * * @param ds * @param sql * @param parameters * @return * @throws SQLException the SQL exception */ @SafeVarargs public static int executeUpdate(final javax.sql.DataSource ds, final String sql, final Object... parameters) throws SQLException { N.checkArgNotNull(ds, "ds"); N.checkArgNotNull(sql, "sql"); final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return executeUpdate(tran.connection(), sql, parameters); } else { final Connection conn = getConnection(ds); try { return executeUpdate(conn, sql, parameters); } finally { releaseConnection(conn, ds); } } } /** * * @param conn * @param sql * @param parameters * @return * @throws SQLException the SQL exception */ @SafeVarargs public static int executeUpdate(final Connection conn, final String sql, final Object... parameters) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); PreparedStatement stmt = null; try { stmt = prepareStmt(conn, sql, parameters); return executeUpdate(stmt); } finally { closeQuietly(stmt); } } /** * * @param ds * @param sql * @param listOfParameters * @return * @throws SQLException the SQL exception */ public static int executeBatchUpdate(final javax.sql.DataSource ds, final String sql, final List> listOfParameters) throws SQLException { return executeBatchUpdate(ds, sql, listOfParameters, DEFAULT_BATCH_SIZE); } /** * * @param ds * @param sql * @param listOfParameters * @param batchSize * @return * @throws SQLException the SQL exception */ public static int executeBatchUpdate(final javax.sql.DataSource ds, final String sql, final List> listOfParameters, final int batchSize) throws SQLException { N.checkArgNotNull(ds, "ds"); N.checkArgNotNull(sql, "sql"); N.checkArgPositive(batchSize, "batchSize"); final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return executeBatchUpdate(tran.connection(), sql, listOfParameters, batchSize); } else if (listOfParameters.size() <= batchSize) { final Connection conn = getConnection(ds); try { return executeBatchUpdate(conn, sql, listOfParameters, batchSize); } finally { releaseConnection(conn, ds); } } else { final SQLTransaction tran2 = JdbcUtil.beginTransaction(ds); int ret = 0; try { ret = executeBatchUpdate(tran2.connection(), sql, listOfParameters, batchSize); tran2.commit(); } finally { tran2.rollbackIfNotCommitted(); } return ret; } } /** * Execute batch update. * * @param conn * @param sql * @param listOfParameters * @return * @throws SQLException the SQL exception */ public static int executeBatchUpdate(final Connection conn, final String sql, final List> listOfParameters) throws SQLException { return executeBatchUpdate(conn, sql, listOfParameters, DEFAULT_BATCH_SIZE); } /** * Execute batch update. * * @param conn * @param sql * @param listOfParameters * @param batchSize * @return * @throws SQLException the SQL exception */ public static int executeBatchUpdate(final Connection conn, final String sql, final List> listOfParameters, final int batchSize) throws SQLException { N.checkArgNotNull(conn); N.checkArgNotNull(sql); N.checkArgPositive(batchSize, "batchSize"); if (N.isNullOrEmpty(listOfParameters)) { return 0; } final ParsedSql parsedSql = ParsedSql.parse(sql); final boolean originalAutoCommit = conn.getAutoCommit(); PreparedStatement stmt = null; boolean noException = false; try { if (originalAutoCommit && listOfParameters.size() > batchSize) { conn.setAutoCommit(false); } stmt = prepareStatement(conn, parsedSql); final Object[] parameters = new Object[1]; int res = 0; int idx = 0; for (Object parameter : listOfParameters) { parameters[0] = parameter; setParameters(parsedSql, stmt, parameters); stmt.addBatch(); if (++idx % batchSize == 0) { res += N.sum(executeBatch(stmt)); } } if (idx % batchSize != 0) { res += N.sum(executeBatch(stmt)); } noException = true; return res; } finally { if (originalAutoCommit && listOfParameters.size() > batchSize) { try { if (noException) { conn.commit(); } else { conn.rollback(); } } finally { try { conn.setAutoCommit(true); } finally { JdbcUtil.closeQuietly(stmt); } } } else { JdbcUtil.closeQuietly(stmt); } } } /** * * @param ds * @param sql * @param listOfParameters * @return * @throws SQLException the SQL exception */ public static long executeLargeBatchUpdate(final javax.sql.DataSource ds, final String sql, final List> listOfParameters) throws SQLException { return executeLargeBatchUpdate(ds, sql, listOfParameters, DEFAULT_BATCH_SIZE); } /** * * @param ds * @param sql * @param listOfParameters * @param batchSize * @return * @throws SQLException the SQL exception */ public static long executeLargeBatchUpdate(final javax.sql.DataSource ds, final String sql, final List> listOfParameters, final int batchSize) throws SQLException { N.checkArgNotNull(ds, "ds"); N.checkArgNotNull(sql, "sql"); N.checkArgPositive(batchSize, "batchSize"); final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return executeLargeBatchUpdate(tran.connection(), sql, listOfParameters, batchSize); } else if (listOfParameters.size() <= batchSize) { final Connection conn = getConnection(ds); try { return executeLargeBatchUpdate(conn, sql, listOfParameters, batchSize); } finally { releaseConnection(conn, ds); } } else { final SQLTransaction tran2 = JdbcUtil.beginTransaction(ds); long ret = 0; try { ret = executeLargeBatchUpdate(tran2.connection(), sql, listOfParameters, batchSize); tran2.commit(); } finally { tran2.rollbackIfNotCommitted(); } return ret; } } /** * Execute batch update. * * @param conn * @param sql * @param listOfParameters * @return * @throws SQLException the SQL exception */ public static long executeLargeBatchUpdate(final Connection conn, final String sql, final List> listOfParameters) throws SQLException { return executeLargeBatchUpdate(conn, sql, listOfParameters, DEFAULT_BATCH_SIZE); } /** * Execute batch update. * * @param conn * @param sql * @param listOfParameters * @param batchSize * @return * @throws SQLException the SQL exception */ public static long executeLargeBatchUpdate(final Connection conn, final String sql, final List> listOfParameters, final int batchSize) throws SQLException { N.checkArgNotNull(conn); N.checkArgNotNull(sql); N.checkArgPositive(batchSize, "batchSize"); if (N.isNullOrEmpty(listOfParameters)) { return 0; } final ParsedSql parsedSql = ParsedSql.parse(sql); final boolean originalAutoCommit = conn.getAutoCommit(); PreparedStatement stmt = null; boolean noException = false; try { if (originalAutoCommit && listOfParameters.size() > batchSize) { conn.setAutoCommit(false); } stmt = prepareStatement(conn, parsedSql); final Object[] parameters = new Object[1]; long res = 0; int idx = 0; for (Object parameter : listOfParameters) { parameters[0] = parameter; setParameters(parsedSql, stmt, parameters); stmt.addBatch(); if (++idx % batchSize == 0) { res += N.sum(executeLargeBatch(stmt)); } } if (idx % batchSize != 0) { res += N.sum(executeLargeBatch(stmt)); } noException = true; return res; } finally { if (originalAutoCommit && listOfParameters.size() > batchSize) { try { if (noException) { conn.commit(); } else { conn.rollback(); } } finally { try { conn.setAutoCommit(true); } finally { JdbcUtil.closeQuietly(stmt); } } } else { JdbcUtil.closeQuietly(stmt); } } } /** * * @param ds * @param sql * @param parameters * @return * @throws SQLException the SQL exception */ @SafeVarargs public static boolean execute(final javax.sql.DataSource ds, final String sql, final Object... parameters) throws SQLException { N.checkArgNotNull(ds, "ds"); N.checkArgNotNull(sql, "sql"); final SQLTransaction tran = getTransaction(ds, sql, CreatedBy.JDBC_UTIL); if (tran != null) { return execute(tran.connection(), sql, parameters); } else { final Connection conn = getConnection(ds); try { return execute(conn, sql, parameters); } finally { releaseConnection(conn, ds); } } } /** * * @param conn * @param sql * @param parameters * @return true, if successful * @throws SQLException the SQL exception */ @SafeVarargs public static boolean execute(final Connection conn, final String sql, final Object... parameters) throws SQLException { N.checkArgNotNull(conn, "conn"); N.checkArgNotNull(sql, "sql"); PreparedStatement stmt = null; try { stmt = prepareStmt(conn, sql, parameters); return JdbcUtil.execute(stmt); } finally { closeQuietly(stmt); } } static ResultSet executeQuery(PreparedStatement stmt) throws SQLException { if (logger.isInfoEnabled() && minExecutionTimeForSQLPerfLog_TL.get() >= 0) { final long startTime = System.currentTimeMillis(); try { return stmt.executeQuery(); } finally { final long elapsedTime = System.currentTimeMillis() - startTime; if (elapsedTime >= minExecutionTimeForSQLPerfLog_TL.get()) { logger.info("[SQL-PERF]: " + elapsedTime + ", " + stmt.toString()); } try { stmt.clearParameters(); } catch (SQLException e) { logger.error("Failed to clear parameters after executeQuery", e); } } } else { try { return stmt.executeQuery(); } finally { try { stmt.clearParameters(); } catch (SQLException e) { logger.error("Failed to clear parameters after executeQuery", e); } } } } static int executeUpdate(PreparedStatement stmt) throws SQLException { if (logger.isInfoEnabled() && minExecutionTimeForSQLPerfLog_TL.get() >= 0) { final long startTime = System.currentTimeMillis(); try { return stmt.executeUpdate(); } finally { final long elapsedTime = System.currentTimeMillis() - startTime; if (elapsedTime >= minExecutionTimeForSQLPerfLog_TL.get()) { logger.info("[SQL-PERF]: " + elapsedTime + ", " + stmt.toString()); } try { stmt.clearParameters(); } catch (SQLException e) { logger.error("Failed to clear parameters after executeUpdate", e); } } } else { try { return stmt.executeUpdate(); } finally { try { stmt.clearParameters(); } catch (SQLException e) { logger.error("Failed to clear parameters after executeUpdate", e); } } } } static int[] executeBatch(Statement stmt) throws SQLException { if (logger.isInfoEnabled() && minExecutionTimeForSQLPerfLog_TL.get() >= 0) { final long startTime = System.currentTimeMillis(); try { return stmt.executeBatch(); } finally { final long elapsedTime = System.currentTimeMillis() - startTime; if (elapsedTime >= minExecutionTimeForSQLPerfLog_TL.get()) { logger.info("[SQL-PERF]: " + elapsedTime + ", " + stmt.toString()); } try { stmt.clearBatch(); } catch (SQLException e) { logger.error("Failed to clear batch parameters after executeBatch", e); } } } else { try { return stmt.executeBatch(); } finally { try { stmt.clearBatch(); } catch (SQLException e) { logger.error("Failed to clear batch parameters after executeBatch", e); } } } } static long[] executeLargeBatch(Statement stmt) throws SQLException { if (logger.isInfoEnabled() && minExecutionTimeForSQLPerfLog_TL.get() >= 0) { final long startTime = System.currentTimeMillis(); try { return stmt.executeLargeBatch(); } finally { final long elapsedTime = System.currentTimeMillis() - startTime; if (elapsedTime >= minExecutionTimeForSQLPerfLog_TL.get()) { logger.info("[SQL-PERF]: " + elapsedTime + ", " + stmt.toString()); } try { stmt.clearBatch(); } catch (SQLException e) { logger.error("Failed to clear batch parameters after executeLargeBatch", e); } } } else { try { return stmt.executeLargeBatch(); } finally { try { stmt.clearBatch(); } catch (SQLException e) { logger.error("Failed to clear batch parameters after executeLargeBatch", e); } } } } static boolean execute(PreparedStatement stmt) throws SQLException { if (logger.isInfoEnabled() && minExecutionTimeForSQLPerfLog_TL.get() >= 0) { final long startTime = System.currentTimeMillis(); try { return stmt.execute(); } finally { final long elapsedTime = System.currentTimeMillis() - startTime; if (elapsedTime >= minExecutionTimeForSQLPerfLog_TL.get()) { logger.info("[SQL-PERF]: " + elapsedTime + ", " + stmt.toString()); } try { stmt.clearParameters(); } catch (SQLException e) { logger.error("Failed to clear parameters after execute", e); } } } else { try { return stmt.execute(); } finally { try { stmt.clearParameters(); } catch (SQLException e) { logger.error("Failed to clear parameters after execute", e); } } } } static void setParameters(final ParsedSql parsedSql, final PreparedStatement stmt, final Object[] parameters) throws SQLException { final int parameterCount = parsedSql.getParameterCount(); if (parameterCount == 0) { return; } else if (N.isNullOrEmpty(parameters)) { throw new IllegalArgumentException( "The count of parameter in sql is: " + parsedSql.getParameterCount() + ". But the specified parameters is null or empty"); } Object[] parameterValues = null; @SuppressWarnings("rawtypes") Type[] parameterTypes = null; if (isEntityOrMapParameter(parsedSql, parameters)) { final List namedParameters = parsedSql.getNamedParameters(); final Object parameter_0 = parameters[0]; parameterValues = new Object[parameterCount]; if (ClassUtil.isEntity(parameter_0.getClass())) { final Object entity = parameter_0; final Class> cls = entity.getClass(); final EntityInfo entityInfo = ParserUtil.getEntityInfo(cls); parameterTypes = new Type[parameterCount]; PropInfo propInfo = null; for (int i = 0; i < parameterCount; i++) { propInfo = entityInfo.getPropInfo(namedParameters.get(i)); if (propInfo == null) { throw new IllegalArgumentException("Parameter for property '" + namedParameters.get(i) + "' is missed"); } parameterValues[i] = propInfo.getPropValue(entity); parameterTypes[i] = propInfo.dbType; } } else if (parameter_0 instanceof Map) { @SuppressWarnings("unchecked") final Map m = (Map ) parameter_0; for (int i = 0; i < parameterCount; i++) { parameterValues[i] = m.get(namedParameters.get(i)); if ((parameterValues[i] == null) && !m.containsKey(namedParameters.get(i))) { throw new IllegalArgumentException("Parameter for property '" + namedParameters.get(i) + "' is missed"); } } } else { final EntityId entityId = (EntityId) parameter_0; for (int i = 0; i < parameterCount; i++) { parameterValues[i] = entityId.get(namedParameters.get(i)); if ((parameterValues[i] == null) && !entityId.containsKey(namedParameters.get(i))) { throw new IllegalArgumentException("Parameter for property '" + namedParameters.get(i) + "' is missed"); } } } } else { parameterValues = getParameterValues(parsedSql, parameters); } setParameters(stmt, parameterCount, parameterValues, parameterTypes); } @SuppressWarnings("rawtypes") static void setParameters(final PreparedStatement stmt, final int parameterCount, final Object[] parameters, final Type[] parameterTypes) throws SQLException { if (N.notNullOrEmpty(parameterTypes) && parameterTypes.length >= parameterCount) { for (int i = 0; i < parameterCount; i++) { parameterTypes[i].set(stmt, i + 1, parameters[i]); } } else if (N.notNullOrEmpty(parameters) && parameters.length >= parameterCount) { for (int i = 0; i < parameterCount; i++) { if (parameters[i] == null) { stmt.setObject(i + 1, parameters[i]); } else { N.typeOf(parameters[i].getClass()).set(stmt, i + 1, parameters[i]); } } } } /** * Gets the parameter values. * * @param parsedSql * @param parameters * @return */ static Object[] getParameterValues(final ParsedSql parsedSql, final Object... parameters) { if ((parameters.length == 1) && (parameters[0] != null)) { if (parameters[0] instanceof Object[] && ((((Object[]) parameters[0]).length) >= parsedSql.getParameterCount())) { return (Object[]) parameters[0]; } else if (parameters[0] instanceof List && (((List>) parameters[0]).size() >= parsedSql.getParameterCount())) { final Collection> c = (Collection>) parameters[0]; return c.toArray(new Object[c.size()]); } } return parameters; } static boolean isEntityOrMapParameter(final ParsedSql parsedSql, final Object... parameters) { if (N.isNullOrEmpty(parsedSql.getNamedParameters())) { return false; } if (N.isNullOrEmpty(parameters) || (parameters.length != 1) || (parameters[0] == null)) { return false; } if (ClassUtil.isEntity(parameters[0].getClass()) || parameters[0] instanceof Map || parameters[0] instanceof EntityId) { return true; } return false; } static final RowFilter INTERNAL_DUMMY_ROW_FILTER = RowFilter.ALWAYS_TRUE; static final RowExtractor INTERNAL_DUMMY_ROW_EXTRACTOR = (rs, outputRow) -> { throw new UnsupportedOperationException("DO NOT CALL ME."); }; /** * * @param rs * @return * @throws SQLException the SQL exception */ public static DataSet extractData(final ResultSet rs) throws SQLException { return extractData(rs, false); } /** * * @param rs * @param closeResultSet * @return * @throws SQLException the SQL exception */ public static DataSet extractData(final ResultSet rs, final boolean closeResultSet) throws SQLException { return extractData(rs, 0, Integer.MAX_VALUE, closeResultSet); } /** * * @param rs * @param offset * @param count * @return * @throws SQLException the SQL exception */ public static DataSet extractData(final ResultSet rs, final int offset, final int count) throws SQLException { return extractData(rs, offset, count, false); } /** * * @param rs * @param offset * @param count * @param closeResultSet * @return * @throws SQLException the SQL exception */ public static DataSet extractData(final ResultSet rs, final int offset, final int count, final boolean closeResultSet) throws SQLException { return extractData(rs, offset, count, INTERNAL_DUMMY_ROW_FILTER, INTERNAL_DUMMY_ROW_EXTRACTOR, closeResultSet); } /** * * @param rs * @param offset * @param count * @param filter * @param closeResultSet * @return * @throws SQLException the SQL exception */ public static DataSet extractData(final ResultSet rs, int offset, int count, final RowFilter filter, final boolean closeResultSet) throws SQLException { return extractData(rs, offset, count, filter, INTERNAL_DUMMY_ROW_EXTRACTOR, closeResultSet); } /** * * @param rs * @param offset * @param count * @param rowExtractor * @param closeResultSet * @return * @throws SQLException the SQL exception */ public static DataSet extractData(final ResultSet rs, int offset, int count, final RowExtractor rowExtractor, final boolean closeResultSet) throws SQLException { return extractData(rs, offset, count, INTERNAL_DUMMY_ROW_FILTER, rowExtractor, closeResultSet); } /** * * @param rs * @param offset * @param count * @param filter * @param rowExtractor * @param closeResultSet * @return * @throws SQLException the SQL exception */ public static DataSet extractData(final ResultSet rs, int offset, int count, final RowFilter filter, final RowExtractor rowExtractor, final boolean closeResultSet) throws SQLException { N.checkArgNotNull(rs, "ResultSet"); N.checkArgNotNegative(offset, "offset"); N.checkArgNotNegative(count, "count"); N.checkArgNotNull(filter, "filter"); N.checkArgNotNull(rowExtractor, "rowExtractor"); try { // TODO [performance improvement]. it will improve performance a lot if MetaData is cached. final ResultSetMetaData rsmd = rs.getMetaData(); final int columnCount = rsmd.getColumnCount(); final List columnNameList = new ArrayList<>(columnCount); final List > columnList = new ArrayList<>(columnCount); for (int i = 0; i < columnCount;) { columnNameList.add(JdbcUtil.getColumnLabel(rsmd, ++i)); columnList.add(new ArrayList<>()); } JdbcUtil.skip(rs, offset); if (filter == INTERNAL_DUMMY_ROW_FILTER) { if (rowExtractor == INTERNAL_DUMMY_ROW_EXTRACTOR) { while (count > 0 && rs.next()) { for (int i = 0; i < columnCount;) { columnList.get(i).add(JdbcUtil.getColumnValue(rs, ++i)); } count--; } } else { final Object[] outputRow = new Object[columnCount]; while (count > 0 && rs.next()) { rowExtractor.accept(rs, outputRow); for (int i = 0; i < columnCount; i++) { columnList.get(i).add(outputRow[i]); } count--; } } } else { if (rowExtractor == INTERNAL_DUMMY_ROW_EXTRACTOR) { while (count > 0 && rs.next()) { if (filter.test(rs)) { for (int i = 0; i < columnCount;) { columnList.get(i).add(JdbcUtil.getColumnValue(rs, ++i)); } count--; } } } else { final Object[] outputRow = new Object[columnCount]; while (count > 0 && rs.next()) { if (filter.test(rs)) { rowExtractor.accept(rs, outputRow); for (int i = 0; i < columnCount; i++) { columnList.get(i).add(outputRow[i]); } count--; } } } } // return new RowDataSet(null, entityClass, columnNameList, columnList); return new RowDataSet(columnNameList, columnList); } finally { if (closeResultSet) { closeQuietly(rs); } } } /** * It's user's responsibility to close the input
resultSet
after the stream is finished. * * @param resultSet * @return */ public static ExceptionalStream