Skip to content

Commit 93aee20

Browse files
committed
Configure default LobHandler to use temporary LOBs on Oracle
JdbcOperationsSessionRepository recently introduced validation when inserting new session attributes in order to prevent data integrity violations in highly concurrent environments. This is done by using INSERT INTO ... SELECT statement to verify existence of session record in parent table. Such arrangement causes problems with Oracle if inserted attribute is of size 4 kb or more. This commit enhances JdbcHttpSessionConfiguration to detect Oracle database is used, and set createTemporaryLob option on default LobHandler to true. Resolves: #1203 See also: #1031
1 parent 3df3b30 commit 93aee20

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

spring-session-jdbc/src/integration-test/java/org/springframework/session/jdbc/AbstractJdbcOperationsSessionRepositoryITests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,21 @@ public void sessionFromStoreResolvesAttributesLazily() {
811811
.isEqualTo("value2");
812812
}
813813

814+
@Test // gh-1203
815+
public void saveWithLargeAttribute() {
816+
String attributeName = "largeAttribute";
817+
int arraySize = 4000;
818+
819+
JdbcOperationsSessionRepository.JdbcSession session = this.repository
820+
.createSession();
821+
session.setAttribute(attributeName, new byte[arraySize]);
822+
this.repository.save(session);
823+
session = this.repository.findById(session.getId());
824+
825+
assertThat(session).isNotNull();
826+
assertThat((byte[]) session.getAttribute(attributeName)).hasSize(arraySize);
827+
}
828+
814829
private String getSecurityName() {
815830
return this.context.getAuthentication().getName();
816831
}

spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
import org.springframework.core.serializer.support.SerializingConverter;
3636
import org.springframework.core.type.AnnotationMetadata;
3737
import org.springframework.jdbc.core.JdbcTemplate;
38+
import org.springframework.jdbc.support.JdbcUtils;
39+
import org.springframework.jdbc.support.MetaDataAccessException;
40+
import org.springframework.jdbc.support.lob.DefaultLobHandler;
3841
import org.springframework.jdbc.support.lob.LobHandler;
3942
import org.springframework.scheduling.annotation.EnableScheduling;
4043
import org.springframework.scheduling.annotation.SchedulingConfigurer;
@@ -102,6 +105,11 @@ public JdbcOperationsSessionRepository sessionRepository() {
102105
if (this.lobHandler != null) {
103106
sessionRepository.setLobHandler(this.lobHandler);
104107
}
108+
else if (requiresTemporaryLob(this.dataSource)) {
109+
DefaultLobHandler lobHandler = new DefaultLobHandler();
110+
lobHandler.setCreateTemporaryLob(true);
111+
sessionRepository.setLobHandler(lobHandler);
112+
}
105113
if (this.springSessionConversionService != null) {
106114
sessionRepository.setConversionService(this.springSessionConversionService);
107115
}
@@ -115,6 +123,17 @@ else if (this.conversionService != null) {
115123
return sessionRepository;
116124
}
117125

126+
private static boolean requiresTemporaryLob(DataSource dataSource) {
127+
try {
128+
String productName = JdbcUtils.extractDatabaseMetaData(dataSource,
129+
"getDatabaseProductName");
130+
return "Oracle".equalsIgnoreCase(JdbcUtils.commonDatabaseName(productName));
131+
}
132+
catch (MetaDataAccessException ex) {
133+
return false;
134+
}
135+
}
136+
118137
public void setMaxInactiveIntervalInSeconds(Integer maxInactiveIntervalInSeconds) {
119138
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
120139
}

0 commit comments

Comments
 (0)