diff --git a/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java b/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java index f6458b256..8473dcaaf 100644 --- a/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java +++ b/spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java @@ -97,20 +97,22 @@ *
* CREATE TABLE SPRING_SESSION ( * PRIMARY_ID CHAR(36) NOT NULL, - * SESSION_ID CHAR(36), + * SESSION_ID CHAR(36) NOT NULL, * CREATION_TIME BIGINT NOT NULL, * LAST_ACCESS_TIME BIGINT NOT NULL, * MAX_INACTIVE_INTERVAL INT NOT NULL, + * EXPIRY_TIME BIGINT NOT NULL, * PRINCIPAL_NAME VARCHAR(100), * CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) * ); * - * CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME); + * CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); + * CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (EXPIRY_TIME); * * CREATE TABLE SPRING_SESSION_ATTRIBUTES ( * SESSION_PRIMARY_ID CHAR(36) NOT NULL, - * ATTRIBUTE_NAME VARCHAR(200), - * ATTRIBUTE_BYTES BYTEA, + * ATTRIBUTE_NAME VARCHAR(200) NOT NULL, + * ATTRIBUTE_BYTES BYTEA NOT NULL, * CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME), * CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE * ); @@ -138,8 +140,8 @@ public class JdbcOperationsSessionRepository implements private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT"; private static final String CREATE_SESSION_QUERY = - "INSERT INTO %TABLE_NAME%(PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, PRINCIPAL_NAME) " + - "VALUES (?, ?, ?, ?, ?, ?)"; + "INSERT INTO %TABLE_NAME%(PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) " + + "VALUES (?, ?, ?, ?, ?, ?, ?)"; private static final String CREATE_SESSION_ATTRIBUTE_QUERY = "INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) " + @@ -152,7 +154,7 @@ public class JdbcOperationsSessionRepository implements "WHERE S.SESSION_ID = ?"; private static final String UPDATE_SESSION_QUERY = - "UPDATE %TABLE_NAME% SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, PRINCIPAL_NAME = ? " + + "UPDATE %TABLE_NAME% SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, EXPIRY_TIME = ?, PRINCIPAL_NAME = ? " + "WHERE PRIMARY_ID = ?"; private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = @@ -175,9 +177,9 @@ public class JdbcOperationsSessionRepository implements "LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID " + "WHERE S.PRINCIPAL_NAME = ?"; - private static final String DELETE_SESSIONS_BY_LAST_ACCESS_TIME_QUERY = + private static final String DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY = "DELETE FROM %TABLE_NAME% " + - "WHERE MAX_INACTIVE_INTERVAL < (? - LAST_ACCESS_TIME) / 1000"; + "WHERE EXPIRY_TIME < ?"; private static final Log logger = LogFactory .getLog(JdbcOperationsSessionRepository.class); @@ -211,7 +213,7 @@ public class JdbcOperationsSessionRepository implements private String listSessionsByPrincipalNameQuery; - private String deleteSessionsByLastAccessTimeQuery; + private String deleteSessionsByExpiryTimeQuery; /** * If non-null, this value is used to override the default value for @@ -333,11 +335,11 @@ public void setListSessionsByPrincipalNameQuery(String listSessionsByPrincipalNa /** * Set the custom SQL query used to delete the sessions by last access time. - * @param deleteSessionsByLastAccessTimeQuery the SQL query string + * @param deleteSessionsByExpiryTimeQuery the SQL query string */ - public void setDeleteSessionsByLastAccessTimeQuery(String deleteSessionsByLastAccessTimeQuery) { - Assert.hasText(deleteSessionsByLastAccessTimeQuery, "Query must not be empty"); - this.deleteSessionsByLastAccessTimeQuery = deleteSessionsByLastAccessTimeQuery; + public void setDeleteSessionsByExpiryTimeQuery(String deleteSessionsByExpiryTimeQuery) { + Assert.hasText(deleteSessionsByExpiryTimeQuery, "Query must not be empty"); + this.deleteSessionsByExpiryTimeQuery = deleteSessionsByExpiryTimeQuery; } /** @@ -385,7 +387,8 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { ps.setLong(3, session.getCreationTime().toEpochMilli()); ps.setLong(4, session.getLastAccessedTime().toEpochMilli()); ps.setInt(5, (int) session.getMaxInactiveInterval().getSeconds()); - ps.setString(6, session.getPrincipalName()); + ps.setLong(6, session.getExpiryTime().toEpochMilli()); + ps.setString(7, session.getPrincipalName()); }); if (!session.getAttributeNames().isEmpty()) { final ListattributeNames = new ArrayList<>(session.getAttributeNames()); @@ -421,8 +424,9 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { ps.setString(1, session.getId()); ps.setLong(2, session.getLastAccessedTime().toEpochMilli()); ps.setInt(3, (int) session.getMaxInactiveInterval().getSeconds()); - ps.setString(4, session.getPrincipalName()); - ps.setString(5, session.primaryKey); + ps.setLong(4, session.getExpiryTime().toEpochMilli()); + ps.setString(5, session.getPrincipalName()); + ps.setString(6, session.primaryKey); }); } Map delta = session.getDelta(); @@ -524,7 +528,7 @@ public Map findByIndexNameAndIndexValue(String indexName, public void cleanUpExpiredSessions() { int deletedCount = this.transactionOperations.execute(transactionStatus -> JdbcOperationsSessionRepository.this.jdbcOperations.update( - JdbcOperationsSessionRepository.this.deleteSessionsByLastAccessTimeQuery, + JdbcOperationsSessionRepository.this.deleteSessionsByExpiryTimeQuery, System.currentTimeMillis())); if (logger.isDebugEnabled()) { @@ -571,8 +575,8 @@ private void prepareQueries() { this.deleteSessionQuery = getQuery(DELETE_SESSION_QUERY); this.listSessionsByPrincipalNameQuery = getQuery(LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY); - this.deleteSessionsByLastAccessTimeQuery = - getQuery(DELETE_SESSIONS_BY_LAST_ACCESS_TIME_QUERY); + this.deleteSessionsByExpiryTimeQuery = + getQuery(DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY); } private void serialize(PreparedStatement ps, int paramIndex, Object attributeValue) @@ -643,6 +647,10 @@ String getPrincipalName() { return PRINCIPAL_NAME_RESOLVER.resolvePrincipal(this); } + Instant getExpiryTime() { + return getLastAccessedTime().plus(getMaxInactiveInterval()); + } + public String getId() { return this.delegate.getId(); } diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-db2.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-db2.sql index c3111d167..b94086714 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-db2.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-db2.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME BIGINT NOT NULL, LAST_ACCESS_TIME BIGINT NOT NULL, MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ); CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-derby.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-derby.sql index c3111d167..b94086714 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-derby.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-derby.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME BIGINT NOT NULL, LAST_ACCESS_TIME BIGINT NOT NULL, MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ); CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-h2.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-h2.sql index c9076c4da..3df06c7be 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-h2.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-h2.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME BIGINT NOT NULL, LAST_ACCESS_TIME BIGINT NOT NULL, MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ); CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-hsqldb.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-hsqldb.sql index c9076c4da..3df06c7be 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-hsqldb.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-hsqldb.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME BIGINT NOT NULL, LAST_ACCESS_TIME BIGINT NOT NULL, MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ); CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-mysql.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-mysql.sql index 28bdf3c1d..136b49e93 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-mysql.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-mysql.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME BIGINT NOT NULL, LAST_ACCESS_TIME BIGINT NOT NULL, MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ) ENGINE=InnoDB; CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-oracle.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-oracle.sql index 69d3892af..774e70430 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-oracle.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-oracle.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME NUMBER(19,0) NOT NULL, LAST_ACCESS_TIME NUMBER(19,0) NOT NULL, MAX_INACTIVE_INTERVAL NUMBER(10,0) NOT NULL, + EXPIRY_TIME NUMBER(19,0) NOT NULL, PRINCIPAL_NAME VARCHAR2(100 CHAR), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ); CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-postgresql.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-postgresql.sql index 570e2ed25..db5088287 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-postgresql.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-postgresql.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME BIGINT NOT NULL, LAST_ACCESS_TIME BIGINT NOT NULL, MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ); CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlite.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlite.sql index abfd8958a..2b45733d1 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlite.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlite.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME INTEGER NOT NULL, LAST_ACCESS_TIME INTEGER NOT NULL, MAX_INACTIVE_INTERVAL INTEGER NOT NULL, + EXPIRY_TIME INTEGER NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ); CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlserver.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlserver.sql index c651dcdaf..c0ef6b477 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlserver.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sqlserver.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME BIGINT NOT NULL, LAST_ACCESS_TIME BIGINT NOT NULL, MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ); CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sybase.sql b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sybase.sql index 1347a5b61..16f29ae8d 100644 --- a/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sybase.sql +++ b/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-sybase.sql @@ -4,12 +4,13 @@ CREATE TABLE SPRING_SESSION ( CREATION_TIME BIGINT NOT NULL, LAST_ACCESS_TIME BIGINT NOT NULL, MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, PRINCIPAL_NAME VARCHAR(100), CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) ) LOCK DATAROWS; CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); -CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (LAST_ACCESS_TIME); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); CREATE TABLE SPRING_SESSION_ATTRIBUTES ( SESSION_PRIMARY_ID CHAR(36) NOT NULL, diff --git a/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java b/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java index 24b97d02d..6d5c9978f 100644 --- a/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java +++ b/spring-session-jdbc/src/test/java/org/springframework/session/jdbc/JdbcOperationsSessionRepositoryTests.java @@ -274,7 +274,7 @@ public void setDeleteSessionsByLastAccessTimeQueryNull() { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("Query must not be empty"); - this.repository.setDeleteSessionsByLastAccessTimeQuery(null); + this.repository.setDeleteSessionsByExpiryTimeQuery(null); } @Test @@ -282,7 +282,7 @@ public void setDeleteSessionsByLastAccessTimeQueryEmpty() { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("Query must not be empty"); - this.repository.setDeleteSessionsByLastAccessTimeQuery(" "); + this.repository.setDeleteSessionsByExpiryTimeQuery(" "); } @Test