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:
committed by
Vedran Pavic
parent
227fab2e42
commit
c523fb591d
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user