/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you 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.openengsb.core.edbi.jdbc;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils;
import org.openengsb.core.edbi.jdbc.sql.PrimaryKeyConstraint;
import org.openengsb.core.edbi.jdbc.sql.Table;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
/**
* JdbcService holds a DataSource and provides several helper methods for spring-jdbc.
*/
public class JdbcService {
private DataSource dataSource;
private JdbcTemplate jdbc;
private NamedParameterJdbcTemplate jdbcn;
public JdbcService(DataSource dataSource) {
this.dataSource = dataSource;
}
public JdbcTemplate jdbc() {
if (jdbc == null) {
jdbc = new JdbcTemplate(dataSource);
}
return jdbc;
}
public NamedParameterJdbcTemplate jdbcn() {
if (jdbcn == null) {
jdbcn = new NamedParameterJdbcTemplate(dataSource);
}
return jdbcn;
}
public DataSource getDataSource() {
return dataSource;
}
public <T> T queryForObject(String sql, Class<T> type) {
return jdbc().queryForObject(sql, type);
}
public <T> T queryForObject(String sql, Class<T> type, Object... args) {
return jdbc().queryForObject(sql, type, args);
}
public Boolean queryForBoolean(String sql, Object... args) {
return queryForObject(sql, Boolean.class, args);
}
public long count(String table) {
return queryForObject("SELECT COUNT(*) FROM " + table, Long.class);
}
public long count(String table, String where, Object... args) {
return queryForObject("SELECT COUNT(*) FROM " + table + " WHERE " + where, Long.class, args);
}
public int insert(String table, String columns, Object... args) {
String sql =
String.format("INSERT INTO `%s` (%s) VALUES (%s)", table, columns,
StringUtils.repeat("?", ",", args.length));
return jdbc().update(sql, args);
}
public int insert(String table, String[] columns, Object[] args) {
return insert(table, StringUtils.join(columns, ","), args);
}
public int insert(String table, Object... args) {
String sql = String.format("INSERT INTO `%s` VALUES (%s)", table, StringUtils.repeat("?", ",", args.length));
return jdbc().update(sql, args);
}
public int[] insert(String table, Collection<String> columns, SqlParameterSource[] records) {
String columnList = StringUtils.join(columns, ",");
String placeholders = ":" + StringUtils.join(columns, ",:");
String sql = String.format("INSERT INTO `%s` (%s) VALUES (%s)", table, columnList, placeholders);
return jdbcn().batchUpdate(sql, records);
}
public int[] insert(Table table, List<IndexRecord> records) {
List<String> columns = table.getColumns().getColumnNames();
return insert(table.getName(), columns, toParameterSourceArray(records));
}
public int[] update(String table, Collection<String> columns, String whereClause, SqlParameterSource[] records) {
String setClauseList = makeNamedSetClauseList(columns);
String sql = String.format("UPDATE `%s` SET %s WHERE %s", table, setClauseList, whereClause);
return jdbcn().batchUpdate(sql, records);
}
public int[] update(Table table, List<IndexRecord> records) {
List<String> columns = table.getColumns().getColumnNames();
String whereClause = makeWhereClause(table.getPrimaryKey());
// FIXME: find an elegant solution for a dynamic SET clause within an UPDATE statement for batch updates
// either column exclusions or find subsets of columns within the list of IndexRecords
IndexRecord record = records.get(0);
columns.retainAll(record.getValues().keySet());
return update(table.getName(), columns, whereClause, toParameterSourceArray(records));
}
public int[] delete(String table, String whereClause, SqlParameterSource[] records) {
String sql = String.format("DELETE FROM `%s` WHERE %s", table, whereClause);
return jdbcn().batchUpdate(sql, records);
}
public int[] delete(Table table, List<IndexRecord> records) {
String whereClause = makeWhereClause(table.getPrimaryKey());
return delete(table.getName(), whereClause, toParameterSourceArray(records));
}
public int delete(String table, String whereClause, Object... args) {
return jdbc().update(String.format("DELETE FROM `%s` WHERE %s", table, whereClause), args);
}
protected SqlParameterSource[] toParameterSourceArray(List<? extends SqlParameterSource> list) {
return list.toArray(new SqlParameterSource[list.size()]);
}
protected String makeNamedSetClauseList(Collection<String> parameters) {
return joinNamedParameters(parameters, "=", ",");
}
protected String makeWhereClause(PrimaryKeyConstraint key) {
return joinNamedParameters(key.getColumns(), "=", " AND ");
}
protected String joinNamedParameters(Collection<String> parameters, String glue, String delimiter) {
StringBuilder str = new StringBuilder(parameters.size() * 20);
Iterator<String> iterator = parameters.iterator();
while (iterator.hasNext()) {
String parameter = iterator.next();
str.append(parameter);
str.append(glue);
str.append(" :");
str.append(parameter);
if (iterator.hasNext()) {
str.append(delimiter);
}
}
return str.toString();
}
}