package ee.esutoniagodesu.repository.project;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.*;
import org.springframework.jdbc.object.StoredProcedure;
import org.springframework.util.Assert;
import javax.sql.DataSource;
import java.math.BigDecimal;
import java.sql.*;
import java.util.Map;
public abstract class AbstractRepository {
private static final Logger log = Logger.getLogger(AbstractRepository.class);
protected final JdbcTemplate jdbcTemplate;
public AbstractRepository(JdbcTemplate jdbcTemplate) {
log.debug("New instance of " + getClass());
this.jdbcTemplate = jdbcTemplate;
}
protected DataSource getDataSource() {
return jdbcTemplate.getDataSource();
}
private static String safeWrap(Object parameter) {
if (parameter == null) return null;
if (parameter instanceof String) {
return "\"" + parameter + '"';
} else if (parameter instanceof byte[]) {
return "byte[length=" + ((byte[]) parameter).length + "]";
} else {
return parameter.toString();
}
}
protected abstract class CustomStoredProcedure extends StoredProcedure implements SqlProvider {
public CustomStoredProcedure(String procedure) {
this(jdbcTemplate, procedure);
}
public CustomStoredProcedure(JdbcTemplate jdbcTemplate, String procedure) {
super(jdbcTemplate, procedure);
prepare();
compile();
}
public String getSql(Object... inParams) {
StringBuilder builder = new StringBuilder();
for (Object p : inParams) {
if (builder.length() > 0) {
builder.append(", ");
}
builder.append(safeWrap(p));
}
return "call " + super.getSql() + "(" + builder.toString() + ")";
}
public Map<String, Object> execute(Object... inParams) {
if (log.isDebugEnabled()) {
log.debug(getSql(inParams));
}
try {
return super.execute(inParams);
} catch (Exception e) {
log.error(getSql(inParams));
throw e;
}
}
public abstract void prepare();
}
protected class CustomStatementBuilder implements SqlProvider {
protected StringBuilder parameters = new StringBuilder();
protected final String sql;
public CustomStatementBuilder(String sql) {
Assert.notNull(sql, "Call string must not be null");
this.sql = sql;
}
public String getSql() {
return this.sql;
}
public void setLong(PreparedStatement s, int index, Long x) throws SQLException {
setParameter(s, index, x, Types.NUMERIC);
}
public void setInt(PreparedStatement s, int index, Integer x) throws SQLException {
setParameter(s, index, x, Types.INTEGER);
}
public void setString(PreparedStatement s, int index, String x) throws SQLException {
setParameter(s, index, x, Types.VARCHAR);
}
public void setDate(PreparedStatement s, int index, java.util.Date x) throws SQLException {
setParameter(s, index, x, Types.DATE);
}
public void setTimestampWithTimezone(PreparedStatement s, int index, java.util.Date x) throws SQLException {
setParameter(s, index, x, Types.TIMESTAMP_WITH_TIMEZONE);
}
public void setTimestamp(PreparedStatement s, int index, java.util.Date x) throws SQLException {
setParameter(s, index, x, Types.TIMESTAMP);
}
public void setParameter(PreparedStatement cs, int key, Object parameter, int otype) throws SQLException {
if (parameter == null) {
cs.setNull(key, otype);
} else {
if (parameter instanceof Boolean) cs.setBoolean(key, (boolean) parameter);
else if (parameter instanceof Byte) cs.setByte(key, (byte) parameter);
else if (parameter instanceof Short) cs.setShort(key, (short) parameter);
else if (parameter instanceof Integer) cs.setInt(key, (int) parameter);
else if (parameter instanceof Long) cs.setLong(key, (long) parameter);
else if (parameter instanceof Float) cs.setFloat(key, (float) parameter);
else if (parameter instanceof Double) cs.setDouble(key, (double) parameter);
else if (parameter instanceof BigDecimal) cs.setBigDecimal(key, (BigDecimal) parameter);
else if (parameter instanceof String) cs.setString(key, (String) parameter);
else if (parameter instanceof byte[]) cs.setBytes(key, (byte[]) parameter);
else if (parameter instanceof java.sql.Date) cs.setDate(key, (java.sql.Date) parameter);
else if (parameter instanceof java.sql.Time) cs.setTime(key, (java.sql.Time) parameter);
else if (parameter instanceof java.sql.Timestamp) cs.setTimestamp(key, (java.sql.Timestamp) parameter);
else if (parameter instanceof java.sql.Array) cs.setArray(key, (java.sql.Array) parameter);
else if (parameter instanceof java.util.Date)
cs.setDate(key, new java.sql.Date(((java.util.Date) parameter).getTime()));
else {
throw new RuntimeException("not implemented");
}
}
if (log.isErrorEnabled()) {
if (parameters.length() > 0) {
parameters.append(", ");
}
parameters.append(safeWrap(parameter));
}
}
}
protected abstract class CustomCallableStatementCreator extends CustomStatementBuilder implements CallableStatementCreator {
private static final String prefix = "call ";
public CustomCallableStatementCreator(String sql) {
super(sql);
}
public CallableStatement createCallableStatement(Connection con) throws SQLException {
return con.prepareCall(sql);
}
@Override
public String getSql() {
String function = sql.substring(sql.indexOf(prefix) + prefix.length(), sql.indexOf("("));
return prefix + function + "(" + parameters.toString() + ")";
}
}
public <T> T execute(CustomCallableStatementCreator csc, CallableStatementCallback<T> action) {
try {
T result = jdbcTemplate.execute(csc, action);
if (log.isDebugEnabled()) {
log.debug(csc.getSql());
}
return result;
} catch (Exception e) {
log.error(csc.getSql());
throw e;
}
}
protected abstract class CustomPreparedStatementCreator extends CustomStatementBuilder implements PreparedStatementCreator, SqlProvider {
public CustomPreparedStatementCreator(String sql) {
super(sql);
}
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
return con.prepareStatement(this.sql);
}
}
public <T> T execute(CustomPreparedStatementCreator csc, PreparedStatementCallback<T> action) {
try {
T result = jdbcTemplate.execute(csc, action);
if (log.isDebugEnabled()) {
log.debug(csc.getSql());
}
return result;
} catch (Exception e) {
log.error(csc.getSql());
throw e;
}
}
}