/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.utils; import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; import nl.strohalm.cyclos.utils.conversion.CoercionHelper; import org.apache.commons.lang.ArrayUtils; /** * Contains helper methods for JDBC access * @author luis */ public class JDBCWrapper { /** * Closes the given connection, ignoring any exceptions */ public static void closeQuietly(final Connection conn) { try { conn.close(); } catch (final Exception e) { // Ignore } } /** * Closes the given result set AND it's statement, ignoring any exceptions */ public static void closeQuietly(final ResultSet rs) { Statement st = null; try { st = rs.getStatement(); } catch (final Exception e) { // Ignore } try { rs.close(); } catch (final Exception e) { // Ignore } closeQuietly(st); } /** * Closes the given statement, ignoring any exceptions */ public static void closeQuietly(final Statement st) { try { st.close(); } catch (final Exception e) { // Ignore } } /** * Set the given positional parameters on a prepared statement, guessing the argument types */ private static void setParameters(final PreparedStatement ps, final Object... parameters) throws SQLException { if (ps == null || ArrayUtils.isEmpty(parameters)) { return; } for (int i = 0; i < parameters.length; i++) { final Object object = parameters[i]; final int index = i + 1; if (object instanceof Number) { ps.setBigDecimal(index, CoercionHelper.coerce(BigDecimal.class, object)); } else if ((object instanceof Calendar) || (object instanceof Date)) { final Calendar cal = CoercionHelper.coerce(Calendar.class, object); ps.setTimestamp(index, new Timestamp(cal.getTimeInMillis())); } else if (object instanceof Boolean) { ps.setBoolean(index, (Boolean) object); } else { ps.setString(index, CoercionHelper.coerce(String.class, object)); } } } private final Connection connection; public JDBCWrapper(final Connection connection) { this.connection = connection; } /** * Closes the underlying connection */ public void close() { closeQuietly(connection); } /** * Commits the underlying connection */ public void commit() throws SQLException { connection.commit(); } /** * Execute a single statement */ public int execute(final String statement, final Object... parameters) throws SQLException { final PreparedStatement ps = connection.prepareStatement(statement); try { setParameters(ps, parameters); return ps.executeUpdate(); } finally { closeQuietly(ps); } } public Connection getConnection() { return connection; } public boolean isHSQLDB() throws SQLException { return connection.getMetaData().getDatabaseProductName().toLowerCase().startsWith("hsql"); } /** * Execute a sql query, returning the open result set */ public ResultSet query(final String sql, final Object... parameters) throws SQLException { return doQuery(sql, ResultSet.CONCUR_READ_ONLY, parameters); } /** * Execute a sql query, returning the first row / column as Long */ public Long readScalarAsLong(final String sql, final Object... parameters) throws SQLException { final PreparedStatement ps = connection.prepareStatement(sql); ResultSet rs = null; try { setParameters(ps, parameters); rs = ps.executeQuery(); if (rs.next()) { final long data = rs.getLong(1); if (rs.wasNull()) { return null; } return data; } else { return null; } } finally { closeQuietly(rs); } } /** * Execute a sql query, returning the first column as long in a list */ public List<Long> readScalarAsLongList(final String sql, final Object... parameters) throws SQLException { final PreparedStatement ps = connection.prepareStatement(sql); ResultSet rs = null; try { setParameters(ps, parameters); rs = ps.executeQuery(); final List<Long> list = new LinkedList<Long>(); while (rs.next()) { list.add(rs.getLong(1)); } return list; } finally { closeQuietly(rs); } } /** * Execute a sql query, returning the first row / column as string */ public String readScalarAsString(final String sql, final Object... parameters) throws SQLException { final PreparedStatement ps = connection.prepareStatement(sql); ResultSet rs = null; try { setParameters(ps, parameters); rs = ps.executeQuery(); if (rs.next()) { return rs.getString(1); } else { return null; } } finally { closeQuietly(rs); } } /** * Execute a sql query, returning the first column as string in a list */ public List<String> readScalarAsStringList(final String sql, final Object... parameters) throws SQLException { final PreparedStatement ps = connection.prepareStatement(sql); ResultSet rs = null; try { setParameters(ps, parameters); rs = ps.executeQuery(); final List<String> list = new LinkedList<String>(); while (rs.next()) { list.add(rs.getString(1)); } return list; } finally { closeQuietly(rs); } } /** * Rollbacks the underlying connection */ public void rollback() throws SQLException { connection.rollback(); } /** * Execute a sql query, returning an updatable, open result set */ public ResultSet updatableQuery(final String sql, final Object... parameters) throws SQLException { return doQuery(sql, ResultSet.CONCUR_UPDATABLE, parameters); } private ResultSet doQuery(final String sql, final int concurrency, final Object... parameters) throws SQLException { final PreparedStatement ps = connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, concurrency); setParameters(ps, parameters); return ps.executeQuery(); } }