spring-session-jdbc 설정
Dependencies
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
</dependency>
</dependencies>
Configurations
2가지 방법으로 설정할 수 있다.
@EnableJdbcHttpSession 어노테이션
@SpringBootApplication
@EnableJdbcHttpSession
@ComponentScan(basePackages = "com.mingoon.test")
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
이 어노테이션으로 Session Timeout, 기본 테이블명, 세션 클린업 주기 (cron), Flush mode, Save mode 등을 설정할 수 있다.
@EnableJdbcHttpSession(tableName = "COMMON_SESSION")
application.yml
spring:
session:
store-type: jdbc
Property는 아래와 같으며, spring.session.jdbc.initialize-schema: always로 설정하면 어플리케이션 기동 시에 세션 및 세션 속성 테이블을 자동으로 생성해주고, spring.session.jdbc.table-name을 통해 테이블 이름도 변경할 수 있다.
수동으로 테이블을 생성하려면 Github의 spring-session 프로젝트를 참고한다.
테이블명 변경
기본적으로 생성되는 테이블은 SPRING_SESSION, SPRING_SESSION_ATTRIBUTES 2개이다. spring.session.jdbc.table-name을 COMMON_SESSION으로 설정하면, COMMON_SESSION, COMMON_SESSION_ATTRIBUTES 로 사용할 수 있다.
여기서 문제가 발생했는데, 발주사에서 생성한 MySQL DB는 개발 시에 테이블, 컬럼명 모두 소문자로 해주길 원했다.
그런데, spring.session.jdbc.table-name을 common_session으로 변경하면 세션 속성 테이블은 common_session_ATTRIBUTES 테이블을 찾게되어 오류가 발생했다.
spring-session-jdbc의 JdbcIndexedSessionRepository.java를 보니 세션 속성 테이블을 사용하는 부분은 모두 이렇게 되어 있어서 발생한 것.
// @formatter:off
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = "INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ "SELECT PRIMARY_ID, ?, ? "
+ "FROM %TABLE_NAME% "
+ "WHERE SESSION_ID = ?";
// @formatter:on
애초에 소문자 따위 고려되지 않게 되어 있었고,
해결방법은..
#1 통일성있게 다른 테이블들 모두 대문자로 해달라고 조른다.
#2 MySQL 설정에 lower_case_table_names를 1로 설정해달라고 한다.
lower_case_table_names | Description |
0 | 대소문자 구분 (Unix, Linux 기본) |
1 | 소문자로 저장되며, 조회 시 대소문자 구분 없음 |
2 | 지정된 대소문자로 저장되며, 조회 시 대소문자 구분 없음 |
#3 JdbcIndexedSessionRepository.java의 쿼리를 변경해준다.
@Configuration
public class SessionConfig {
@Bean
public SessionRepositoryCustomizer<JdbcIndexedSessionRepository> tableNameSessionRepositoryCustomizer() {
return sessionRepository -> {
String createSessionAttribute = "INSERT INTO spring_session_attributes(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) "
+ "SELECT PRIMARY_ID, ?, ? "
+ "FROM spring_session "
+ "WHERE SESSION_ID = ?";
String getSession = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
+ "FROM spring_session S "
+ "LEFT OUTER JOIN spring_session_attributes SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
+ "WHERE S.SESSION_ID = ?";
String updateSessionAttribute = "UPDATE spring_session_attributes SET ATTRIBUTE_BYTES = ? "
+ "WHERE SESSION_PRIMARY_ID = ? "
+ "AND ATTRIBUTE_NAME = ?";
String deleteSessionAttribute = "DELETE FROM spring_session_attributes "
+ "WHERE SESSION_PRIMARY_ID = ? "
+ "AND ATTRIBUTE_NAME = ?";
String listSessionsByPrincipalName = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES "
+ "FROM spring_session S "
+ "LEFT OUTER JOIN spring_session_attributes SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID "
+ "WHERE S.PRINCIPAL_NAME = ?";
sessionRepository.setCreateSessionAttributeQuery( createSessionAttribute );
sessionRepository.setGetSessionQuery( getSession );
sessionRepository.setUpdateSessionAttributeQuery( updateSessionAttribute );
sessionRepository.setDeleteSessionAttributeQuery( deleteSessionAttribute );
sessionRepository.setListSessionsByPrincipalNameQuery( listSessionsByPrincipalName );
};
}
}
불필요한 코드가 추가된다..
결국 이런 코드가 들어가도 괜찮겠냐고 물어봐서, 고개를 절레절레하더니 다시 모든 테이블명을 대문자로 가기로 결정.. =ㅂ=