package org.simpleflatmapper.jdbc.spring;
import org.simpleflatmapper.jdbc.*;
import org.simpleflatmapper.util.CheckedConsumer;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcOperations;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
public class JdbcTemplateCrud<T, K> {
private final JdbcOperations jdbcTemplate;
private final Crud<T, K> crud;
public JdbcTemplateCrud(JdbcOperations jdbcOperations, Crud<T, K> crud) {
this.jdbcTemplate = jdbcOperations;
this.crud = crud;
}
/**
* insert value into the db through the specified connection.
*
* @param value the value
* @throws DataAccessException if an error occurs
*/
public void create(final T value) throws DataAccessException {
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
crud.create(connection, value);
return null;
}
});
}
/**
* insert values into the db through the specified connection.
*
* @param values the values
* @throws DataAccessException if an error occurs
*/
public void create(final Collection<T> values) throws DataAccessException {
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
crud.create(connection, values);
return null;
}
});
}
/**
* insert value into the db through the specified connection.
* Callback keyConsumer with the generated key if one was.
*
* @param value the value
* @param keyConsumer the key consumer
* @param <RH> the type of keyConsumer
* @return the keyConsumer
* @throws DataAccessException
*/
public <RH extends CheckedConsumer<? super K>> RH create(final T value, final RH keyConsumer) throws DataAccessException {
return
jdbcTemplate.execute(new ConnectionCallback<RH>() {
@Override
public RH doInConnection(Connection connection) throws SQLException, DataAccessException {
return crud.create(connection, value, keyConsumer);
}
});
}
/**
* insert values into the db through the specified connection.
* Callback keyConsumer for the generated keys.
*
* @param values the values
* @param keyConsumer the key consumer
* @param <RH> the type of keyConsumer
* @return the keyConsumer
* @throws DataAccessException
*/
public <RH extends CheckedConsumer<? super K>> RH create(final Collection<T> values, final RH keyConsumer) throws DataAccessException {
return
jdbcTemplate.execute(new ConnectionCallback<RH>() {
@Override
public RH doInConnection(Connection connection) throws SQLException, DataAccessException {
return crud.create(connection, values, keyConsumer);
}
});
}
/**
* retrieve the object with the specified key.
*
* @param key the key
* @return the object or null if not found
* @throws DataAccessException if an error occurs
*/
public T read(final K key) throws DataAccessException {
return
jdbcTemplate.execute(new ConnectionCallback<T>() {
@Override
public T doInConnection(Connection connection) throws SQLException, DataAccessException {
return crud.read(connection, key);
}
});
}
/**
* retrieve the objects with the specified keys and pass them to the consumer.
*
* @param keys the keys
* @param consumer the handler that is callback for each row
* @throws DataAccessException if an error occurs
*/
public <RH extends CheckedConsumer<? super T>> RH read(final Collection<K> keys, final RH consumer) throws DataAccessException {
return
jdbcTemplate.execute(new ConnectionCallback<RH>() {
@Override
public RH doInConnection(Connection connection) throws SQLException, DataAccessException {
return crud.read(connection, keys, consumer);
}
});
}
/**
* update the object.
*
* @param value the object
* @throws DataAccessException if an error occurs
*/
public void update(final T value) throws DataAccessException {
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
crud.update(connection, value);
return null;
}
});
}
/**
* update the objects.
*
* @param values the objects
* @throws DataAccessException if an error occurs
*/
public void update(final Collection<T> values) throws DataAccessException {
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
crud.update(connection, values);
return null;
}
});
}
/**
* delete the object with the specified key.
*
* @param key the key
* @throws DataAccessException if an error occurs
*/
public void delete(final K key) throws DataAccessException {
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
crud.delete(connection, key);
return null;
}
});
}
/**
* delete the objects with the specified keys.
*
* @param keys the keys
* @throws DataAccessException if an error occurs
*/
public void delete(final List<K> keys) throws DataAccessException {
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
crud.delete(connection, keys);
return null;
}
});
}
/**
* UPSERT only supported on Mysql
* @param value the value
* @throws DataAccessException
* @throws UnsupportedOperationException
*/
public void createOrUpdate(final T value) throws DataAccessException {
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
crud.createOrUpdate(connection, value);
return null;
}
});
}
/**
* UPSERT only supported on Mysql
* @param values the values to upsert
* @throws DataAccessException
* @throws UnsupportedOperationException
*/
public void createOrUpdate(final Collection<T> values) throws DataAccessException {
jdbcTemplate.execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
crud.createOrUpdate(connection, values);
return null;
}
});
}
/**
* UPSERT only supported on Mysql.
* Used the callback with caution has Mysql will return an incremented id event for when no insert actually occurred.
* @param value the value to upsert
* @param keyConsumer generated key consumer
* @param <RH> the keyConsumer type
* @return the keyConsumer
* @throws DataAccessException
*/
public <RH extends CheckedConsumer<? super K>> RH createOrUpdate(final T value, final RH keyConsumer) throws DataAccessException {
return jdbcTemplate.execute(new ConnectionCallback<RH>() {
@Override
public RH doInConnection(Connection connection) throws SQLException, DataAccessException {
return crud.createOrUpdate(connection, value, keyConsumer);
}
});
}
/**
* UPSERT only supported on Mysql.
* Used the callback with caution has Mysql will return an incremented id event for when no insert actually occurred.
* @param values the values to insert
* @param keyConsumer generated key consumer
* @param <RH> the keyConsumer type
* @return the keyConsumer
* @throws DataAccessException
*/
public <RH extends CheckedConsumer<? super K>> RH createOrUpdate(final Collection<T> values, final RH keyConsumer) throws DataAccessException {
return jdbcTemplate.execute(new ConnectionCallback<RH>() {
@Override
public RH doInConnection(Connection connection) throws SQLException, DataAccessException {
return crud.createOrUpdate(connection, values, keyConsumer);
}
});
}
public <P> ConnectedSelectQuery<T, P> where(String whereClause, Type paramClass) {
SelectQuery<T, P> selectQuery = crud.where(whereClause, paramClass);
return new ConnectedSelectQuery<T, P>(selectQuery,
new JdbcTemplateTransactionTemplate(jdbcTemplate));
}
private static class JdbcTemplateTransactionTemplate implements TransactionTemplate {
private final JdbcOperations jdbcOperations;
private JdbcTemplateTransactionTemplate(JdbcOperations jdbcOperations) {
this.jdbcOperations = jdbcOperations;
}
@Override
public <R> R doInTransaction(final SQLFunction<? super Connection, ? extends R> sqlFunction) throws DataAccessException {
return jdbcOperations.execute(new ConnectionCallback<R>() {
@Override
public R doInConnection(Connection con) throws SQLException, DataAccessException {
return sqlFunction.apply(con);
}
});
}
}
}