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-1151
This commit is contained in:
Vedran Pavic
2018-08-13 06:28:42 +02:00
parent 6b7fc3af08
commit 3a972bef76
2 changed files with 34 additions and 7 deletions

View File

@@ -743,6 +743,31 @@ public abstract class AbstractJdbcOperationsSessionRepositoryITests {
assertThat(session.<String>getAttribute("testName")).isEqualTo("testValue2");
}
@Test // gh-1151
public void saveDeleted() {
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
this.repository.save(session);
session = this.repository.findById(session.getId());
this.repository.deleteById(session.getId());
session.setLastAccessedTime(Instant.now());
this.repository.save(session);
assertThat(this.repository.findById(session.getId())).isNull();
}
@Test // gh-1151
public void saveDeletedAddAttribute() {
JdbcOperationsSessionRepository.JdbcSession session = this.repository.createSession();
this.repository.save(session);
session = this.repository.findById(session.getId());
this.repository.deleteById(session.getId());
session.setLastAccessedTime(Instant.now());
session.setAttribute("testName", "testValue1");
this.repository.save(session);
assertThat(this.repository.findById(session.getId())).isNull();
}
private String getSecurityName() {
return this.context.getAuthentication().getName();
}

View File

@@ -144,7 +144,9 @@ public class JdbcOperationsSessionRepository implements
private static final String CREATE_SESSION_ATTRIBUTE_QUERY =
"INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) " +
"VALUES (?, ?, ?)";
"SELECT PRIMARY_ID, ?, ? " +
"FROM %TABLE_NAME% " +
"WHERE SESSION_ID = ?";
private static final String GET_SESSION_QUERY =
"SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES " +
@@ -499,9 +501,9 @@ public class JdbcOperationsSessionRepository implements
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
String attributeName = attributeNames.get(i);
ps.setString(1, session.primaryKey);
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());
}
@Override
@@ -514,9 +516,9 @@ public class JdbcOperationsSessionRepository implements
else {
this.jdbcOperations.update(this.createSessionAttributeQuery, (ps) -> {
String attributeName = attributeNames.get(0);
ps.setString(1, session.primaryKey);
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());
});
}
}