SqlSessionFactory 클래스 정리
▤ 목차
MyBatis를 배우는데 자연스럽게 사용하지만 궁금한 인터페이스가 있었다.
SqlSessionFactory는 MyBatis 프레임워크에서 중요한 인터페이스 중 하나이다.
이 인터페이스는 데이터베이스와의 연결을 설정하고 SQL 세션을 생성하는 역할을 한다.
이름에서 알 수 있는 점은, Factory 패턴이 사용되었다는 점이다.
✔ SqlSessionFactory 인터페이스 정의
SqlSessionFactory는 MyBatis에서 DB와의 연결을 설정하고 SQL 세션을 생성하는 인터페이스이다.
MyBatis는 데이터베이스 접근 계층을 제공한다.
개발자는 SQL 매퍼 파일을 통해 SQL 쿼리와 자바 객체 간의 매핑을 할 수 있다.
⌨ 인터페이스 정의
public interface SqlSessionFactory {
SqlSession openSession();
SqlSession openSession(boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, Connection connection);
Configuration getConfiguration();
}
이렇게 Interface로 정의되어 있다.
대부분의 인터페이스는 openSession 메서드를 오버로딩해 놓은 것을 알 수 있다.
마지막에 getConfiguration()메서드가 있는데 이를 통해 해당 SqlSessionFatory의 설정 정보를 반환한다.
✔ SqlSessionFactory 주요 메서드
🔦 openSession()
SqlSession openSession();
기본적으로 DB와 새로운 SQL 세션을 열때 사용한다.
이 메서드는 기본 설정으로 세션을 연다.
🔦 openSession(boolean autoCommit)
SqlSession openSession(boolean autoCommit);
세션을 열때 자동 커밋 여부를 지정할 수 있다.
autoCommit이 true인 경우, 세션이 열리면 자동으로 커밋한다.
false인 경우, 명시적으로 커밋을 호출해야한다.
즉, 데이터 변경 사항을 반영을 자동으로할지, 수동으로 할지 정하는 것이다.
🔦 openSession(Connection connection)
SqlSession openSession(Connection connection);
JDBC 연결을 사용해 세션을 사용한다.
MyBatis는 이미 존재하는 JDBC 연결을 이용해 세션을 시작할 수 있다.
🔦 openSession(TransactionIsolationLevel level)
SqlSession openSession(TransactionIsolationLevel level);
지정된 트랜잭션 레벨(DB 트랜잭션의 격리 수준)을 설정할 수 있다.
DB 트랜잭션은 동시에 여러 사용자가 접근하는 경우, 발생할 수 있는 문제를 관리하기 위해 격리 수준을 설정한다.
🔦 openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType);
지정된 execuType으로 세션을 연다.
ExecuType은 SQL 실행 방식을 제어하는 역할을 한다.
기본값은 ExecutorType.SIMPLE 이라고 한다.
🔦 getConfiguration()
Configuration getConfiguration();
해당 SqlSessionFactory 인스턴스의 설정 정보를 반환한다.
설정 정보에는 데이터베이스 연결 정보, sql 매퍼 위치, 타입 별칭(alias) 등 정보가 포함되어 있다.
✔ SqlSessionFactory의 역할
📌SQL 세션 생성
위의 코드에서 봤다시피 데이터베이스와 연결을 설정하고 SQL 세션을 생성한다.
( DB와 실제 연결을 설정하고 해당 연결을 통해 SQL 쿼리를 실행할 준비를 하는 과정 을 )
📌 환경 설정 관리
데이터 베이스 연결 정보, 트랜잭션 관리 방법, SQL 매퍼 파일 위치 등의 환경 설정을 관리한다.
📌스레드 세이프
SqlSessionFactory 는 여러 스레드에서 안전하게 공유할 수있도록 설계해야한다.
보통 전체에서 하나의 인스턴스를 사용한다.
즉, 싱글톤 패턴(어떤 클래스의 인스턴스가 단 하나만 생성되고 인스턴스에 대한 전역적 접근(static)을 제공)을 의미한다.
📌 트랜잭션 관리
SqlSessionFactory 를 통해 생성된 객체는 데이터베이스 트랜잭션을 관리한다.
필요에 따라 커밋(commit) 또는 롤백(rollback)할 수 있다.
// SQL 세션 생성
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
// SQL 세션을 사용하여 데이터베이스 조회 등의 작업을 수행
List<User> userList = sqlSession.selectList("pack.mapper.UserMapper.getAllUsers");
// 작업 완료 후 세션을 커밋
sqlSession.commit();
} finally {
sqlSession.close(); // 세션 닫기
}
이 경우, 관리자가 직접 commit을 하기에 auto-commit은 false일 것이다.
SQL 세션 == HTTP 세션 ?
SQL 세션을 연다는 의미
DB와 실제 연결을 설정하고 해당 연결을 통해 SQL 쿼리를 실행할 준비를 하는 과정을 말한다.
웹에서 HTTP 세션(쿠키에 넣는)과는 다른 의미이다.
⌨ SQL 세션의 의미
- 데이터베이스 연결 설정
세션을 열때, 먼저 데이터베이스 연결을 설정한다.
JDBC 드라이버를 로드하고 데이터베이스 서버에 접속하기 위한 연결 정보를 설정한다. - SQL 쿼리 실행
SQL 세션을 통해 DB의 SQL쿼리를 실행할 수 있다.
MyBatis에서는 sql 쿼리를 xml 파일이나 어노테이션을 정의하고 sqlSession을 통해 쿼리를 호출하고 실행한다. - 자원 관리
SQL 세션을 사용하고 난 후 반드시 세션을 닫아야한다.
이 과정에서 사용된 데이터베이스 연결과 관련 자원들을 해제하고, 메모리 리소스를 정리한다.
세션을 닫지 않으면 데이터베이스 연결이 계속 유지된다.
유지가 계속되면 성능 저하와 자원 누수가 된다. - 트랜잭션 관리
SQL 세션은 트랜잭션을 관리한다.
트랜잭션은 데이터베이스에서 하나의 작업 단위를 의미하며 성공적으로 완료되거나 실패할 수 있다.
SQL 세션을 열면 트랜잭션의 시작을 알린다.
이에 (설정에 따라 다르겠지만) 커밋과 롤백을 수행할 수 있다.
💻 HTTP 세션과 차이점
HTTP 세션 | SQL 세션 | |
목적 | 클라이언트와 서버 간의 상태 유지를 위해 사용된다. 주로 사용자 인증정보나 장바구니 등.. 데이터를 저장하고 관리한다. |
DB와 연결과 SQL 작업을 관리하는데 사용된다. |
유지 시간 | 클라이언트가 해당 웹 애플리케이션에 접속한 후 일정 시간동안 유지된다. | SQL 작업을 수행하는 동안만 유지되며 작업이 완료되면 세션을 닫아야한다. |
범위 | 웹 애플리케이션 내에서 유효하다. | 데이터베이스 서버와의 연결을 관리하는 범위이다. |
👏 중요
SQL 세션을 연다는 의미는 DB와 연결을 설정하는 것이다.
SQL 작업을 수행할 수 있는 상태를 만드는 과정을 말한다.
JDBC 드라이버를 로드하고 데이터베이스 서버에 접속하여 트랜잭션을 관리하고 SQL 쿼리를 실행하고 결과를 받아온다.
DB의 효율적인 상호작용을 위한 필수적인 과정이다.
😊정리를 하다가..
정리를 하다가, 아래와 같은 문장을 보면서 synchroized 키워드를 사용하는 싱글톤과의 차이가 궁금해졌다.
SqlSessionFactory 는 여러 스레드에서 안전하게 공유할 수있도록 설계해야한다.
보통 전체에서 하나의 인스턴스를 사용한다.
여러 검색과 비교 결결과적으로 try{..}를 사용한(정적 초기화 블록) 코드가 좋은 코드라는 결론이 났다.
1번(정적 초기화 블록 사용) | 2번 (synchronized 사용) | |
성능 vs 초기화 지연 | 클래스 로드 시 한번만 초기화 된다. | 처음 호출 될때마다 초기화된다. 지연 초기화를 제공한다. |
동기화 필요성 | 정적 초기화 블록을 사용하여 동기화 문제를 방지한다. | synchronized 키워드를 사용하여 동시 접근에 대한 문제를 해결했다. 멀티스레드 환경에서 안전한 접근을 보장해야하는 경우 동기화 처리를 추가할 수 있다. |
예외처리와 리소스 관리 | 리소스 해제와 예외처리가 필요한 경우, 명시적으로 처리하는 것이 바람직하다. | 내부적으로 콜백함수를 사용했기에 명시적으로 해제하는 부분이 없다. |
코드는 다양하게 구현할 수 있어서 비교하는 재미도 있지만 어떤게 더 좋은 코드인지 찾아보는 과정에서 많은 시간이 뺏긴다. 계속하다보면 개념이 체화되어 시간이 줄어들겠지..라는 생각이다.
언젠가는 뭐가 더 좋은지 생각하면 이유가 딱딱 정리되겠지?
아직 잘 몰라서, 이런 것들을 찾아보고나면 너무 작은 부분에 시간을 쏟은게 아닌가,하는 불안감?이 생긴다.
아무튼 정리끝!
디자인 패턴에 대한 정리가 필요하단 생각을 한다.