io.github.mjcro.mosaic.handlers.sql.mysql.MySqlMinimalLayout Maven / Gradle / Ivy
Show all versions of mosaic Show documentation
package io.github.mjcro.mosaic.handlers.sql.mysql;
import io.github.mjcro.mosaic.KeySpec;
import io.github.mjcro.mosaic.handlers.sql.Mapper;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Minimal layout to store data.
*
* Contains following columns:
* - id - incremental, int64
* - linkId - identifier of anchor link
* - typeId - identifier of type
* - ... - value column(s), names are provided by mapper
*
* Whenever data is requested to be deleted, it will be actually deleted from
* database.
*/
public class MySqlMinimalLayout extends MySqlLayout {
public static final MySqlMinimalLayout DEFAULT = new MySqlMinimalLayout(
true,
"linkId",
"typeId"
);
/**
* Constructs minimal MySQL layout with given column names.
*
* @param detectTransaction If true, layout will detect transactional context and insert "FOR UPDATE"
* while reading data.
* @param columnLinkId Column name to store link identifier.
* @param columnTypeId Column name to store type identifier.
*/
public MySqlMinimalLayout(boolean detectTransaction, String columnLinkId, String columnTypeId) {
super(detectTransaction, columnLinkId, columnTypeId);
}
@Override
public Map>> findByLinkId(
Mapper mapper,
Connection connection,
String tableName,
Collection linkIds,
Collection keys
) throws SQLException {
HashMap reverseMap = new HashMap<>();
for (final Key key : keys) {
reverseMap.put(key.getTypeId(), key);
}
String[] columns = mapper.getColumnNames();
StringBuilder sb = new StringBuilder();
sb.append("SELECT ").append(escapeName(columnLinkId)).append(",").append(escapeName(columnTypeId));
for (String column : columns) {
sb.append(",").append(escapeName(column));
}
sb.append(" FROM ").append(escapeName(tableName)).append(" WHERE");
sb.append(" ").append(escapeName(columnLinkId)).append(" IN (");
for (int i = 0; i < linkIds.size(); i++) {
if (i > 0) {
sb.append(",");
}
sb.append("?");
}
sb.append(")");
sb.append(" AND ").append(escapeName(columnTypeId)).append(" IN (");
for (int i = 0; i < keys.size(); i++) {
if (i > 0) {
sb.append(",");
}
sb.append("?");
}
sb.append(")");
if (insideTransaction(connection)) {
// Inside transaction
sb.append(" FOR UPDATE");
}
Map>> response = new HashMap<>();
int offset = 1;
try (PreparedStatement stmt = connection.prepareStatement(sb.toString())) {
for (final Long id : linkIds) {
stmt.setLong(offset++, id);
}
for (final Key key : keys) {
stmt.setInt(offset++, key.getTypeId());
}
try (ResultSet rs = stmt.executeQuery()) {
if (rs.isBeforeFirst()) {
while (rs.next()) {
if (rs.isAfterLast()) {
break;
}
long linkId = rs.getLong(1);
Key key = reverseMap.get(rs.getInt(2));
if (key == null) {
// Key not resolved
continue;
}
Object value = mapper.readObjectValue(rs, 3);
if (!response.containsKey(linkId)) {
response.put(linkId, new HashMap<>());
}
Map> subMap = response.get(linkId);
if (!subMap.containsKey(key)) {
subMap.put(key, new ArrayList<>());
}
subMap.get(key).add(value);
}
}
}
}
return response;
}
@Override
public void store(
Mapper mapper,
Connection connection,
String tableName,
long linkId,
Map extends KeySpec, List