상세 컨텐츠

본문 제목

spring-session-jdbc 설정

Spring Framework

by mingoon.com 2022. 4. 8. 10:47

본문

반응형

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 );
		};
	}
}

불필요한 코드가 추가된다..

 

결국 이런 코드가 들어가도 괜찮겠냐고 물어봐서, 고개를 절레절레하더니 다시 모든 테이블명을 대문자로 가기로 결정.. =ㅂ=


댓글 영역