📄 jdbcutils.java
字号:
/*
* Copyright 2002-2004 the original author or authors.
*
* 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 org.springframework.jdbc.support;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.jdbc.datasource.DataSourceUtils;
/**
* Generic utility methods for working with JDBC.
* @author Isabelle Muszynski
* @author Thomas Risberg
* @author Juergen Hoeller
*/
public class JdbcUtils {
private static final Log logger = LogFactory.getLog(JdbcUtils.class);
/**
* Close the given JDBC Statement and ignore any thrown exception.
* This is useful for typical finally blocks in manual JDBC code.
* @param stmt the JDBC Statement to close
*/
public static void closeStatement(Statement stmt) {
if (stmt != null) {
try {
stmt.close();
}
catch (SQLException ex) {
logger.warn("Could not close JDBC Statement", ex);
}
}
}
/**
* Close the given JDBC ResultSet and ignore any thrown exception.
* This is useful for typical finally blocks in manual JDBC code.
* @param rs the JDBC ResultSet to close
*/
public static void closeResultSet(ResultSet rs) {
if (rs != null) {
try {
rs.close();
}
catch (SQLException ex) {
logger.warn("Could not close JDBC ResultSet", ex);
}
}
}
/**
* Extract database meta data.
* <p>This method will open a connection to the database and retrieve the database metadata.
* Since this method is called before the exception translation feature is configured for
* a datasource, this method can not rely on the SQLException translation functionality.
* <p>Any exceptions will be wrapped in a MetaDataAccessException. This is a checked exception
* and any calling code should catch and handle this exception. You can just log the
* error and hope for the best, but there is probably a more serious error that will
* reappear when you try to access the database again.
* @param dataSource the DataSource to use
* @param action callback that will do the actual work
* @return object containing the extracted information
*/
public static Object extractDatabaseMetaData(DataSource dataSource, DatabaseMetaDataCallback action)
throws MetaDataAccessException {
Connection con = null;
try {
con = DataSourceUtils.getConnection(dataSource);
if (con != null) {
return action.processMetaData(con.getMetaData());
}
else {
throw new MetaDataAccessException("Error while getting connection");
}
}
catch (CannotGetJdbcConnectionException ex) {
//throw checked exception - we don't want this to be fatal?
throw new MetaDataAccessException("Error while getting connection",ex);
}
catch (DataAccessException ex) {
//throw checked exception - we don't want this to be fatal?
throw new MetaDataAccessException("Error while extracting DatabaseMetaData",ex);
}
catch (SQLException ex) {
//throw checked exception - we don't want this to be fatal?
throw new MetaDataAccessException("Error while extracting DatabaseMetaData",ex);
}
finally {
DataSourceUtils.closeConnectionIfNecessary(con, dataSource);
}
}
/**
* Count the occurrences of the character <code>placeholder</code> in an SQL string
* <code>str</code>. The character <code>placeholder</code> is not counted if it
* appears within a literal as determined by the <code>delim</code> that is passed in.
* Delegates to the overloaded method that takes a String with multiple delimiters.
* @param str string to search in. Returns 0 if this is null
* @param placeholder the character to search for and count.
* @param delim the delimiter for character literals.
*/
public static int countParameterPlaceholders(String str, char placeholder, char delim) {
return countParameterPlaceholders(str, placeholder, ""+delim);
}
/**
* Count the occurrences of the character <code>placeholder</code> in an SQL string
* <code>str</code>. The character <code>placeholder</code> is not counted if it
* appears within a literal as determined by the <code>delimiters</code> that are passed in.
* <p>Examples: If one of the delimiters is the single quote, and the character to count the
* occurrences of is the question mark, then:
* <p><code>The big ? 'bad wolf?'</code> gives a count of one.<br>
* <code>The big ?? bad wolf</code> gives a count of two.<br>
* <code>The big 'ba''ad?' ? wolf</code> gives a count of one.
* <p>The grammar of the string passed in should obey the rules of the JDBC spec
* which is close to no rules at all: one placeholder per parameter, and it should
* be valid SQL for the target database.
* @param str string to search in. Returns 0 if this is null
* @param placeholder the character to search for and count.
* @param delimiters the delimiters for character literals.
*/
public static int countParameterPlaceholders(String str, char placeholder, String delimiters) {
int count = 0;
boolean insideLiteral = false;
int activeLiteral = -1;
for (int i = 0; str != null && i < str.length(); i++) {
if (str.charAt(i) == placeholder) {
if (!insideLiteral)
count++;
}
else {
if (delimiters.indexOf(str.charAt(i)) > -1) {
if (!insideLiteral) {
insideLiteral = true;
activeLiteral = delimiters.indexOf(str.charAt(i));
}
else {
if (activeLiteral == delimiters.indexOf(str.charAt(i))) {
insideLiteral = false;
activeLiteral = -1;
}
}
}
}
}
return count;
}
/**
* Check that a SQL type is numeric.
* @param sqlType the SQL type to be checked
* @return if the type is numeric
*/
public static boolean isNumeric(int sqlType) {
return Types.BIT == sqlType || Types.BIGINT == sqlType || Types.DECIMAL == sqlType ||
Types.DOUBLE == sqlType || Types.FLOAT == sqlType || Types.INTEGER == sqlType ||
Types.NUMERIC == sqlType || Types.REAL == sqlType || Types.SMALLINT == sqlType ||
Types.TINYINT == sqlType;
}
/**
* Translate a SQL type into one of a few values:
* All integer types are translated to Integer.
* All real types are translated to Double.
* All string types are translated to String.
* All other types are left untouched.
* @param sqlType the type to be translated into a simpler type
* @return the new SQL type
*/
public static int translateType(int sqlType) {
int retType = sqlType;
if (Types.BIT == sqlType || Types.TINYINT == sqlType || Types.SMALLINT == sqlType ||
Types.INTEGER == sqlType) {
retType = Types.INTEGER;
}
else if (Types.CHAR == sqlType || Types.VARCHAR == sqlType) {
retType = Types.VARCHAR;
}
else if (Types.DECIMAL == sqlType || Types.DOUBLE == sqlType || Types.FLOAT == sqlType ||
Types.NUMERIC == sqlType || Types.REAL == sqlType) {
retType = Types.NUMERIC;
}
return retType;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -