Insert new attributes conditionally in JDBC repo

At present, the insert of new attributes in JdbcOperationsSessionRepository is done unconditionally. This can cause data integrity violation errors with concurrent requests, where one request attempts to add new session attribute while the other, concurrent request, deletes the session.

This commit addresses the described scenario by executing insert of new attributes conditionally on presence of parent record.

Closes gh-1153
This commit is contained in:
Vedran Pavic
2018-08-13 06:28:42 +02:00
parent b50a4e247e
commit cb6f7fdfa6
2 changed files with 34 additions and 7 deletions

View File

@@ -608,6 +608,31 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
assertThat(this.repository.getSession(session.getId())).isNull();
}
@Test // gh-1153
public void saveDeleted() {
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
this.repository.save(session);
session = this.repository.getSession(session.getId());
this.repository.delete(session.getId());
session.setLastAccessedTime(System.currentTimeMillis());
this.repository.save(session);
assertThat(this.repository.getSession(session.getId())).isNull();
}
@Test // gh-1153
public void saveDeletedAddAttribute() {
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
this.repository.save(session);
session = this.repository.getSession(session.getId());
this.repository.delete(session.getId());
session.setLastAccessedTime(System.currentTimeMillis());
session.setAttribute("testName", "testValue1");
this.repository.save(session);
assertThat(this.repository.getSession(session.getId())).isNull();
}
private String getSecurityName() {
return this.context.getAuthentication().getName();
}

View File

@@ -143,7 +143,9 @@ public class JdbcOperationsSessionRepository implements
private static final String CREATE_SESSION_ATTRIBUTE_QUERY =
"INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) " +
"VALUES (?, ?, ?)";
"SELECT SESSION_ID, ?, ? " +
"FROM %TABLE_NAME% " +
"WHERE SESSION_ID = ?";
private static final String GET_SESSION_QUERY =
"SELECT S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES " +
@@ -398,9 +400,9 @@ public class JdbcOperationsSessionRepository implements
public void setValues(PreparedStatement ps, int i) throws SQLException {
String attributeName = attributeNames.get(i);
ps.setString(1, session.getId());
ps.setString(2, attributeName);
serialize(ps, 3, session.getAttribute(attributeName));
ps.setString(1, attributeName);
serialize(ps, 2, session.getAttribute(attributeName));
ps.setString(3, session.getId());
}
public int getBatchSize() {
@@ -465,9 +467,9 @@ public class JdbcOperationsSessionRepository implements
new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, session.getId());
ps.setString(2, entry.getKey());
serialize(ps, 3, entry.getValue());
ps.setString(1, entry.getKey());
serialize(ps, 2, entry.getValue());
ps.setString(3, session.getId());
}
});