package com.codepoetics.octarine.jdbc; import com.codepoetics.octarine.records.Key; import com.codepoetics.octarine.records.Record; import org.pcollections.HashTreePMap; import org.pcollections.PMap; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class TableMapping { public static interface PreparedStatementParameterSetter { void setParameters(PreparedStatement preparedStatement) throws SQLException; } public static interface BatchPreparedStatementParameterSetter { void setParameters(PreparedStatement preparedStatement, int index) throws SQLException; int getBatchSize(); } public static TableMapping forTable(String tableName) { return new TableMapping(tableName, HashTreePMap.empty()); } private final String tableName; private final PMap<Key<?>, String> columnNameMap; private TableMapping(String tableName, PMap<Key<?>, String> columnNameMap) { this.tableName = tableName; this.columnNameMap = columnNameMap; } public TableMapping with(Key<?> key, String columnName) { return new TableMapping(tableName, columnNameMap.plus(key, columnName)); } public PreparedStatementParameterSetter settingParametersFor(Record record) { return ps -> { int idx = 1; for (Map.Entry<Key<?>, String> entry : columnNameMap.entrySet()) { ps.setObject(idx++, record.get(entry.getKey()).orElse(null)); } }; } public BatchPreparedStatementParameterSetter settingParametersFor(List<Record> records) { return new BatchPreparedStatementParameterSetter() { @Override public void setParameters(PreparedStatement preparedStatement, int index) throws SQLException { settingParametersFor(records.get(index)).setParameters(preparedStatement); } @Override public int getBatchSize() { return records.size(); } }; } public PreparedStatement createInsertStatement(Connection connection) throws SQLException { return connection.prepareStatement(createInsertSql()); } public String createInsertSql() { return String.format("INSERT INTO %s (%s) VALUES (%s)", tableName, String.join(",", columnNameMap.values()), String.join(",", columnNameMap.values().stream() .map(v -> "?") .collect(Collectors.toList()))); } public TableMapping with(Key<?> key) { return with(key, key.name()); } }