org.vertexium.sql.collections.SqlMap Maven / Gradle / Ivy
The newest version!
package org.vertexium.sql.collections;
import org.skife.jdbi.v2.*;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
import org.skife.jdbi.v2.util.ByteArrayMapper;
import org.skife.jdbi.v2.util.IntegerMapper;
import org.skife.jdbi.v2.util.StringMapper;
import org.vertexium.VertexiumSerializer;
import org.vertexium.util.CloseableUtils;
import org.vertexium.util.VertexiumLogger;
import org.vertexium.util.VertexiumLoggerFactory;
import javax.sql.DataSource;
import java.io.Closeable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
@SuppressWarnings("NullableProblems")
public class SqlMap extends AbstractMap {
private static final VertexiumLogger LOGGER = VertexiumLoggerFactory.getLogger(SqlMap.class);
protected final String tableName;
protected final String keyColumnName;
protected final String valueColumnName;
private final DBI dbi;
private final VertexiumSerializer serializer;
private final ResultSetMapper> entrySetMapper;
private Object storableContext;
public SqlMap(String tableName, String keyColumnName, String valueColumnName, DataSource dataSource,
VertexiumSerializer serializer) {
this.tableName = tableName;
this.keyColumnName = keyColumnName;
this.valueColumnName = valueColumnName;
this.dbi = new DBI(dataSource);
this.serializer = serializer;
this.entrySetMapper = new ResultSetMapper>() {
public MapEntry map(int index, ResultSet rs, StatementContext ctx) throws SQLException {
String key = rs.getString(SqlMap.this.keyColumnName);
byte[] value = rs.getBytes(SqlMap.this.valueColumnName);
return new MapEntry<>(key, value);
}
};
}
public void setStorableContext(Object storableContext) {
this.storableContext = storableContext;
}
@Override
public Set> entrySet() {
final Handle handle = dbi.open();
final Query> query = handle
.createQuery(String.format(
"select %s, %s from %s order by %s", keyColumnName, valueColumnName, tableName, keyColumnName))
.map(entrySetMapper);
return new IteratingSet>() {
@Override
public Iterator> createIterator() {
return new QueryResultIterator, MapEntry>(query, handle) {
@Override
public Entry next() {
MapEntry stringifiedEntry = resultIterator.next();
String key = stringifiedEntry.getKey();
T value = withContainer(serializer.bytesToObject(stringifiedEntry.getValue()));
return new MapEntry<>(key, value);
}
};
}
};
}
@Override
public Set keySet() {
final Handle handle = dbi.open();
final Query query = handle
.createQuery(String.format("select %s from %s order by %s", keyColumnName, tableName, keyColumnName))
.map(StringMapper.FIRST);
return new IteratingSet() {
@Override
public Iterator createIterator() {
return new QueryResultIterator<>(query, handle);
}
};
}
@Override
public Collection values() {
final Handle handle = dbi.open();
final Query query = handle
.createQuery(String.format("select %s from %s order by %s", valueColumnName, tableName, keyColumnName))
.map(ByteArrayMapper.FIRST);
return new IteratingSet() {
@Override
public Iterator createIterator() {
return new QueryResultIterator(query, handle) {
@Override
public T next() {
return withContainer(serializer.bytesToObject(resultIterator.next()));
}
};
}
};
}
@Override
public boolean containsKey(Object key) {
try (Handle handle = dbi.open()){
return handle
.createQuery(String.format(
"select count(*) %s from %s where %s = ?", keyColumnName, tableName, keyColumnName))
.bind(0, key)
.map(IntegerMapper.FIRST)
.first() > 0;
}
}
@Override
public boolean containsValue(Object value) {
try (Handle handle = dbi.open()) {
return handle
.createQuery(String.format(
"select count(*) %s from %s where %s = ?", valueColumnName, tableName, valueColumnName))
.bind(0, serializer.objectToBytes(value))
.map(IntegerMapper.FIRST)
.first() > 0;
}
}
@Override
public int size() {
try (Handle handle = dbi.open()) {
return handle
.createQuery(String.format("select count(*) from %s", tableName))
.map(IntegerMapper.FIRST)
.first();
}
}
@Override
public void clear() {
try (Handle handle = dbi.open()) {
handle.execute(String.format("delete from %s", tableName));
}
}
@Override
public T remove(Object key) {
T value = get(key);
try (Handle handle = dbi.open()) {
handle.execute(String.format("delete from %s where %s = ?", tableName, keyColumnName), key);
return withoutContainer(value);
}
}
@Override
public T get(Object key) {
try (Handle handle = dbi.open()) {
return withContainer(serializer.bytesToObject(handle
.createQuery(String.format(
"select %s from %s where %s = ?", valueColumnName, tableName, keyColumnName))
.bind(0, key)
.map(ByteArrayMapper.FIRST)
.first()));
}
}
@Override
public T put(String key, T value) {
byte[] byteArrayValue = serializer.objectToBytes(withContainer(value));
T previous = get(key);
try (Handle handle = dbi.open()) {
if (previous == null) {
handle.execute(String.format(
"insert into %s (%s, %s) values (?, ?)", tableName, keyColumnName, valueColumnName),
key, byteArrayValue);
} else {
handle.execute(String.format(
"update %s set %s = ? where %s = ?", tableName, valueColumnName, keyColumnName),
byteArrayValue, key);
}
updateAdditionalColumns(handle, key, value);
}
return withoutContainer(previous);
}
private void updateAdditionalColumns(Handle handle, String key, T value) {
Map additional = additionalColumns(key, value);
if (!additional.isEmpty()) {
StringBuilder updateSql = new StringBuilder(String.format("update %s set ", tableName));
List