Deserialize attributes lazily in JdbcOperationsSessionRepository

Instead of deserializing all of the session attributes as they are read from the database, deserialize as #getAttribute requests them.

See: #1133
This commit is contained in:
Craig Andrews
2018-07-20 12:58:33 -04:00
committed by Vedran Pavic
parent 227fab2e42
commit c523fb591d

View File

@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
@@ -530,7 +531,7 @@ public class JdbcOperationsSessionRepository implements
public void setValues(PreparedStatement ps, int i) throws SQLException {
String attributeName = attributeNames.get(i);
ps.setString(1, attributeName);
serialize(ps, 2, session.getAttribute(attributeName));
bytesToLob(ps, 2, serialize(session.getAttribute(attributeName)));
ps.setString(3, session.getId());
}
@@ -545,7 +546,7 @@ public class JdbcOperationsSessionRepository implements
this.jdbcOperations.update(this.createSessionAttributeQuery, (ps) -> {
String attributeName = attributeNames.get(0);
ps.setString(1, attributeName);
serialize(ps, 2, session.getAttribute(attributeName));
bytesToLob(ps, 2, serialize(session.getAttribute(attributeName)));
ps.setString(3, session.getId());
});
}
@@ -559,7 +560,7 @@ public class JdbcOperationsSessionRepository implements
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
String attributeName = attributeNames.get(i);
serialize(ps, 1, session.getAttribute(attributeName));
bytesToLob(ps, 1, serialize(session.getAttribute(attributeName)));
ps.setString(2, session.primaryKey);
ps.setString(3, attributeName);
}
@@ -574,7 +575,7 @@ public class JdbcOperationsSessionRepository implements
else {
this.jdbcOperations.update(this.updateSessionAttributeQuery, (ps) -> {
String attributeName = attributeNames.get(0);
serialize(ps, 1, session.getAttribute(attributeName));
bytesToLob(ps, 1, serialize(session.getAttribute(attributeName)));
ps.setString(2, session.primaryKey);
ps.setString(3, attributeName);
});
@@ -657,18 +658,26 @@ public class JdbcOperationsSessionRepository implements
getQuery(DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY);
}
private void serialize(PreparedStatement ps, int paramIndex, Object attributeValue)
private void bytesToLob(PreparedStatement ps, int paramIndex, byte[] bytes)
throws SQLException {
this.lobHandler.getLobCreator().setBlobAsBytes(ps, paramIndex,
(byte[]) this.conversionService.convert(attributeValue,
TypeDescriptor.valueOf(Object.class),
TypeDescriptor.valueOf(byte[].class)));
bytes);
}
private Object deserialize(ResultSet rs, String columnName)
private byte[] serialize(Object attributeValue) {
return (byte[]) this.conversionService.convert(attributeValue,
TypeDescriptor.valueOf(Object.class),
TypeDescriptor.valueOf(byte[].class));
}
private byte[] lobToBytes(ResultSet rs, String columnName)
throws SQLException {
return this.lobHandler.getBlobAsBytes(rs, columnName);
}
private Object deserialize(byte[] bytes) {
return this.conversionService.convert(
this.lobHandler.getBlobAsBytes(rs, columnName),
bytes,
TypeDescriptor.valueOf(byte[].class),
TypeDescriptor.valueOf(Object.class));
}
@@ -679,6 +688,34 @@ public class JdbcOperationsSessionRepository implements
}
static final <Z> Supplier<Z> constantSupplier(Z value) {
if (value == null) {
return null;
}
else {
return () -> value;
}
}
static final <Z> Supplier<Z> lazily(Supplier<Z> supplier) {
if (supplier == null) {
return null;
}
else {
return new Supplier<Z>() {
private Z value;
@Override
public Z get() {
if (this.value == null) {
this.value = supplier.get();
}
return this.value;
}
};
}
}
/**
* The {@link Session} to use for {@link JdbcOperationsSessionRepository}.
*
@@ -748,7 +785,13 @@ public class JdbcOperationsSessionRepository implements
@Override
public <T> T getAttribute(String attributeName) {
return this.delegate.getAttribute(attributeName);
Supplier<T> supplier = this.delegate.getAttribute(attributeName);
if (supplier == null) {
return null;
}
else {
return supplier.get();
}
}
@Override
@@ -783,7 +826,7 @@ public class JdbcOperationsSessionRepository implements
? oldDeltaValue
: DeltaValue.UPDATED);
}
this.delegate.setAttribute(attributeName, attributeValue);
this.delegate.setAttribute(attributeName, constantSupplier(attributeValue));
if (PRINCIPAL_NAME_INDEX_NAME.equals(attributeName) ||
SPRING_SECURITY_CONTEXT.equals(attributeName)) {
this.changed = true;
@@ -875,7 +918,8 @@ public class JdbcOperationsSessionRepository implements
}
String attributeName = rs.getString("ATTRIBUTE_NAME");
if (attributeName != null) {
session.delegate.setAttribute(attributeName, deserialize(rs, "ATTRIBUTE_BYTES"));
byte[] bytes = lobToBytes(rs, "ATTRIBUTE_BYTES");
session.delegate.setAttribute(attributeName, lazily(() -> deserialize(bytes)));
}
sessions.add(session);
}