All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.inftec.ju.db.DbConnectionImpl Maven / Gradle / Ivy

There is a newer version: 4.5.1-11
Show newest version
package ch.inftec.ju.db;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;

import ch.inftec.ju.db.DbRowUtils.DbRowsImpl;
import ch.inftec.ju.util.JuStringUtils;
import ch.inftec.ju.util.change.DbAction;
import ch.inftec.ju.util.change.DbActionUtils;


/**
 * Implementation of the DbConnection interface.
 * 

* Expects a DataSource and JdbcTemplate to be autowired by Spring. * @author Martin * */ final class DbConnectionImpl implements DbConnection { Logger log = LoggerFactory.getLogger(DbConnectionImpl.class); @Autowired private JdbcTemplate jdbcTemplate; @Autowired private DataSource dataSource; private String name; private String schemaName; // /** // * Creates a new connection creator with the specified name. // * @param name Unique name of the connection // * @param entityManagerFactory Factory used to created an EntityManager that will back // * up the connection // */ // protected DbConnectionImpl(String name, String schemaName, EntityManagerFactory entityManagerFactory) { // this.name = name; // this.schemaName = schemaName; // } @Override public String getName() { return this.name; } @Override public String getSchemaName() { return this.schemaName; } @Override public List getTableNames() throws JuDbException { DbMetaData md = new DbMetaData(); return md.getTableNames(); } @Override public String getPrimaryColumnName(String tableName) throws JuDbException { DbMetaData md = new DbMetaData(); return md.getPrimaryColumnName(tableName); } @Override public List getColumnNames(String tableName) throws JuDbException { DbMetaData md = new DbMetaData(); return Arrays.asList(md.getColumnNames(tableName)); } @Override public DbQueryRunner getQueryRunner() { return new DbQueryRunnerImpl(this); } @Override public Connection getConnection() { return DataSourceUtils.getConnection(this.dataSource); } /** * Helper class to wrap around a DatabaseMetaData object. * Make sure to call the close() method when the object is not used any longer. * @author Martin * */ private class DbMetaData { private DatabaseMetaData metaData; private ResultSet rs; /** * Creates a new DbMetaData instance. If an exception occurs, close will be called * implicitly. * @throws JuDbException If the MetaData cannot be accessed */ public DbMetaData() throws JuDbException { try { this.metaData = DbConnectionImpl.this.getConnection().getMetaData(); } catch (SQLException ex) { throw new JuDbException("Couldn't access DatabaseMetaData", ex); } } public List getTableNames() throws JuDbException { try { this.rs = this.metaData.getTables(getSchemaName(), null, null, new String[]{"TABLE"}); List tableNames = new ArrayList<>(); while (rs.next()) { String tableName = rs.getString("TABLE_NAME"); tableNames.add(tableName.toUpperCase()); } Collections.sort(tableNames); return tableNames; } catch (JuDbException ex) { throw ex; } catch (SQLException ex) { throw new JuDbException("Couldn't evaluate table names", ex); } finally { JuDbUtils.closeQuietly(this.rs); this.rs = null; } } /** * Gets the primary column name for the specified table. * @param tableName Table name * @return Primary column name * @throws JuDbException If the primary column name cannot be evaluated */ public String getPrimaryColumnName(String tableName) throws JuDbException { try { this.rs = this.metaData.getPrimaryKeys(null, null, tableName.toUpperCase()); String columnName = null; if (rs.next()) columnName = rs.getString("COLUMN_NAME"); else throw new JuDbException("Couldn't evaluate primary key for table " + tableName); if (rs.next()) { throw new JuDbException("Driver returned multiple primary keys for table " + tableName); } return columnName.toUpperCase(); } catch (JuDbException ex) { throw ex; } catch (SQLException ex) { throw new JuDbException("Couldn't evaluate primary key for table " + tableName, ex); } finally { JuDbUtils.closeQuietly(this.rs); this.rs = null; } } /** * Gets all column names of the specified table in the order they are defined, or rather in the * order the driver returns them. * @param tableName Table name * @return Column names of the table * @throws JuDbException If the column names cannot be evaluated */ public String[] getColumnNames(String tableName) throws JuDbException { try { this.rs = this.metaData.getColumns(null, null, tableName.toUpperCase(), null); ArrayList columnNames = new ArrayList(); while (rs.next()) { String columnName = rs.getString("COLUMN_NAME"); columnNames.add(columnName.toUpperCase()); } if (columnNames.size() == 0) { throw new JuDbException("Couldn't evaluate column names for table " + tableName + ": Driver returned empty ResultSet."); } return (String[])columnNames.toArray(new String[0]); } catch (JuDbException ex) { throw ex; } catch (SQLException ex) { throw new JuDbException("Couldn't evaluate primary key for table " + tableName, ex); } finally { JuDbUtils.closeQuietly(this.rs); this.rs = null; } } } @Override public String toString() { return JuStringUtils.toString(this, "name", this.getName()); } /** * Implementation of the DbQueryRunner interface that works with DbConnection * instances. * @author TGDMEMAE * */ private final class DbQueryRunnerImpl implements DbQueryRunner { private DbConnectionImpl dbConnection; /** * Creates a new DbQueryRunner using the specified DbConnection. * @param dbConnection DbConnection instance */ public DbQueryRunnerImpl(DbConnectionImpl dbConnection) { this.dbConnection = dbConnection; } /** * Gets a connection to the database. * @return Connection instance * @throws JuDbException If the connection cannot be established */ private Connection getConnection() throws JuDbException { return this.dbConnection.getConnection(); } @Override public DbRowsImpl query(String query, Object... params) throws JuDbException { try { QueryRunner qr = new QueryRunner(); return qr.query(this.getConnection(), query, new DbRowResultSetHandler(), this.processParams(params)); } catch (SQLException ex) { throw new JuDbException("Couldn't execute query: " + query, ex); } } @Override public int update(String query, Object... params) throws JuDbException { try { QueryRunner qr = new QueryRunner(); return qr.update(this.getConnection(), query, this.processParams(params)); } catch (SQLException ex) { throw new JuDbException("Couldn't execute update: " + query, ex); } } @Override public DbRow primaryKeyQuery(String tableName, Object primaryKeyValue) throws JuDbException { String selectQry = "SELECT * FROM " + tableName + " WHERE " + this.dbConnection.getPrimaryColumnName(tableName) + "=?"; DbRows dbRows = this.query(selectQry, primaryKeyValue); if (dbRows.getRowCount() > 1) { throw new JuDbException("PrimaryKeyQuery for " + tableName + " with key=" + primaryKeyValue + ". Expected exactly 1 row, but got " + dbRows.getRowCount()); } return dbRows.getRowCount() == 0 ? null : dbRows.getRow(0); } /** * Executes a select * query on the specified table that returns no rows. Can be used * to obtain an empty DbRows instance. * @param tableName Table name * @return DbRows instance with no rows * @throws JuDbException If the query fails */ @Override public DbRow emptyRowQuery(String tableName) throws JuDbException { String selectQry = "SELECT * FROM " + tableName + " WHERE 1=0"; return this.query(selectQry).getBaseRow(); } @Override public DbAction getUpdateAction(String tableName, Object primaryKeyValue) throws JuDbException { DbRow row = this.primaryKeyQuery(tableName, primaryKeyValue); return row == null ? null : DbActionUtils.newUpdateAction(this.dbConnection, row, tableName).getAction(); } @Override public DbAction getInsertAction(String tableName) throws JuDbException { return DbActionUtils.newInsertAction(this.dbConnection, tableName).getAction(); } @Override public DbAction getDeleteAction(String tableName, Object primaryKeyValue) throws JuDbException { return DbActionUtils.newDeleteAction(this.dbConnection, tableName, primaryKeyValue); } /** * Processes the parameters that are send to the QueryRunner. *

* For instance, this will convert a java.util.Date to a java.sql.Date * @param object Parameters array * @return Array with converted parameters */ private Object[] processParams(Object[] params) { Object[] newParams = Arrays.copyOf(params, params.length); for (int i = 0; i < newParams.length; i++) { Object param = newParams[i]; if (param != null) { if (param.getClass() == java.util.Date.class) { newParams[i] = new java.sql.Date(((java.util.Date)param).getTime()); } } } return newParams; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy