/*
* Copyright 2017 LinkedIn Corp.
*
* 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 azkaban.db;
import java.sql.Connection;
import org.apache.commons.dbutils.DbUtils;
import org.apache.log4j.Logger;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import com.google.inject.Inject;
import static java.util.Objects.*;
/**
* Implement AZ DB related operations. This class is thread safe.
*/
public class DatabaseOperatorImpl implements DatabaseOperator {
private static final Logger logger = Logger.getLogger(DatabaseOperatorImpl.class);
private final QueryRunner queryRunner;
/**
* Note: this queryRunner should include a concrete {@link AzkabanDataSource} inside.
*
* @param queryRunner
*/
@Inject
public DatabaseOperatorImpl(QueryRunner queryRunner){
requireNonNull(queryRunner.getDataSource(), "data source must not be null.");
this.queryRunner = queryRunner;
}
/**
* query method Implementation. it will call {@link AzkabanDataSource#getConnection()} inside queryrunner.query.
*/
@Override
public <T> T query(String baseQuery, ResultSetHandler<T> resultHandler, Object...params) throws SQLException {
try{
return queryRunner.query(baseQuery, resultHandler, params);
} catch (SQLException ex){
// todo kunkun-tang: Retry logics should be implemented here.
logger.error("query failed", ex);
throw ex;
}
}
/**
* transaction method Implementation.
*
*/
@Override
public <T> T transaction(SQLTransaction<T> operations) throws SQLException {
Connection conn = null;
try{
conn = queryRunner.getDataSource().getConnection();
conn.setAutoCommit(false);
DatabaseTransOperator transOperator = new DatabaseTransOperatorImpl(queryRunner, conn);
T res = operations.execute(transOperator);
conn.commit();
return res;
} catch (SQLException ex) {
// todo kunkun-tang: Retry logics should be implemented here.
logger.error("transaction failed", ex);
throw ex;
} finally {
DbUtils.closeQuietly(conn);
}
}
/**
* update implementation. it will call {@link AzkabanDataSource#getConnection()} inside queryrunner.update.
*
* @param updateClause sql statements to execute
* @param params Initialize the PreparedStatement's IN parameters
* @return the number of rows being affected by update
* @throws SQLException
*/
@Override
public int update(String updateClause, Object...params) throws SQLException {
try{
return queryRunner.update(updateClause, params);
} catch (SQLException ex){
// todo kunkun-tang: Retry logics should be implemented here.
logger.error("update failed", ex);
throw ex;
}
}
}