Skip to content

Commit c523fb5

Browse files
candrewsvpavic
authored andcommitted
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
1 parent 227fab2 commit c523fb5

File tree

1 file changed

+56
-12
lines changed

1 file changed

+56
-12
lines changed

spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Map;
2929
import java.util.Set;
3030
import java.util.UUID;
31+
import java.util.function.Supplier;
3132
import java.util.stream.Collectors;
3233

3334
import org.apache.commons.logging.Log;
@@ -530,7 +531,7 @@ private void insertSessionAttributes(JdbcSession session, List<String> attribute
530531
public void setValues(PreparedStatement ps, int i) throws SQLException {
531532
String attributeName = attributeNames.get(i);
532533
ps.setString(1, attributeName);
533-
serialize(ps, 2, session.getAttribute(attributeName));
534+
bytesToLob(ps, 2, serialize(session.getAttribute(attributeName)));
534535
ps.setString(3, session.getId());
535536
}
536537

@@ -545,7 +546,7 @@ public int getBatchSize() {
545546
this.jdbcOperations.update(this.createSessionAttributeQuery, (ps) -> {
546547
String attributeName = attributeNames.get(0);
547548
ps.setString(1, attributeName);
548-
serialize(ps, 2, session.getAttribute(attributeName));
549+
bytesToLob(ps, 2, serialize(session.getAttribute(attributeName)));
549550
ps.setString(3, session.getId());
550551
});
551552
}
@@ -559,7 +560,7 @@ private void updateSessionAttributes(JdbcSession session, List<String> attribute
559560
@Override
560561
public void setValues(PreparedStatement ps, int i) throws SQLException {
561562
String attributeName = attributeNames.get(i);
562-
serialize(ps, 1, session.getAttribute(attributeName));
563+
bytesToLob(ps, 1, serialize(session.getAttribute(attributeName)));
563564
ps.setString(2, session.primaryKey);
564565
ps.setString(3, attributeName);
565566
}
@@ -574,7 +575,7 @@ public int getBatchSize() {
574575
else {
575576
this.jdbcOperations.update(this.updateSessionAttributeQuery, (ps) -> {
576577
String attributeName = attributeNames.get(0);
577-
serialize(ps, 1, session.getAttribute(attributeName));
578+
bytesToLob(ps, 1, serialize(session.getAttribute(attributeName)));
578579
ps.setString(2, session.primaryKey);
579580
ps.setString(3, attributeName);
580581
});
@@ -657,18 +658,26 @@ private void prepareQueries() {
657658
getQuery(DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY);
658659
}
659660

660-
private void serialize(PreparedStatement ps, int paramIndex, Object attributeValue)
661+
private void bytesToLob(PreparedStatement ps, int paramIndex, byte[] bytes)
661662
throws SQLException {
662663
this.lobHandler.getLobCreator().setBlobAsBytes(ps, paramIndex,
663-
(byte[]) this.conversionService.convert(attributeValue,
664+
bytes);
665+
}
666+
667+
private byte[] serialize(Object attributeValue) {
668+
return (byte[]) this.conversionService.convert(attributeValue,
664669
TypeDescriptor.valueOf(Object.class),
665-
TypeDescriptor.valueOf(byte[].class)));
670+
TypeDescriptor.valueOf(byte[].class));
666671
}
667672

668-
private Object deserialize(ResultSet rs, String columnName)
673+
private byte[] lobToBytes(ResultSet rs, String columnName)
669674
throws SQLException {
675+
return this.lobHandler.getBlobAsBytes(rs, columnName);
676+
}
677+
678+
private Object deserialize(byte[] bytes) {
670679
return this.conversionService.convert(
671-
this.lobHandler.getBlobAsBytes(rs, columnName),
680+
bytes,
672681
TypeDescriptor.valueOf(byte[].class),
673682
TypeDescriptor.valueOf(Object.class));
674683
}
@@ -679,6 +688,34 @@ private enum DeltaValue {
679688

680689
}
681690

691+
static final <Z> Supplier<Z> constantSupplier(Z value) {
692+
if (value == null) {
693+
return null;
694+
}
695+
else {
696+
return () -> value;
697+
}
698+
}
699+
700+
static final <Z> Supplier<Z> lazily(Supplier<Z> supplier) {
701+
if (supplier == null) {
702+
return null;
703+
}
704+
else {
705+
return new Supplier<Z>() {
706+
private Z value;
707+
708+
@Override
709+
public Z get() {
710+
if (this.value == null) {
711+
this.value = supplier.get();
712+
}
713+
return this.value;
714+
}
715+
};
716+
}
717+
}
718+
682719
/**
683720
* The {@link Session} to use for {@link JdbcOperationsSessionRepository}.
684721
*
@@ -748,7 +785,13 @@ public String changeSessionId() {
748785

749786
@Override
750787
public <T> T getAttribute(String attributeName) {
751-
return this.delegate.getAttribute(attributeName);
788+
Supplier<T> supplier = this.delegate.getAttribute(attributeName);
789+
if (supplier == null) {
790+
return null;
791+
}
792+
else {
793+
return supplier.get();
794+
}
752795
}
753796

754797
@Override
@@ -783,7 +826,7 @@ public void setAttribute(String attributeName, Object attributeValue) {
783826
? oldDeltaValue
784827
: DeltaValue.UPDATED);
785828
}
786-
this.delegate.setAttribute(attributeName, attributeValue);
829+
this.delegate.setAttribute(attributeName, constantSupplier(attributeValue));
787830
if (PRINCIPAL_NAME_INDEX_NAME.equals(attributeName) ||
788831
SPRING_SECURITY_CONTEXT.equals(attributeName)) {
789832
this.changed = true;
@@ -875,7 +918,8 @@ public List<JdbcSession> extractData(ResultSet rs) throws SQLException, DataAcce
875918
}
876919
String attributeName = rs.getString("ATTRIBUTE_NAME");
877920
if (attributeName != null) {
878-
session.delegate.setAttribute(attributeName, deserialize(rs, "ATTRIBUTE_BYTES"));
921+
byte[] bytes = lobToBytes(rs, "ATTRIBUTE_BYTES");
922+
session.delegate.setAttribute(attributeName, lazily(() -> deserialize(bytes)));
879923
}
880924
sessions.add(session);
881925
}

0 commit comments

Comments
 (0)