6. SqlSessionFactory 객체 준비
DAO 객체에 주입할 SqlSessionFactory 객체를 준비한다. spms.listeners.ContextLoaderListener 클래스를 열고 다음과 같이 편집한다.
package spms.listeners;
import java.io.InputStream;
import javax.naming.InitialContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import spms.context.ApplicationContext;
import spms.controls.LogInController;
import spms.controls.LogOutController;
import spms.controls.MemberAddController;
import spms.controls.MemberDeleteController;
import spms.controls.MemberListController;
import spms.controls.MemberUpdateController;
import spms.dao.MySqlMemberDao;
//SqlSessionFactory 객체 준비
@WebListener
public class ContextLoaderListener implements ServletContextListener {
static ApplicationContext applicationContext;
//ApplicationContext 객체 얻을 때 사용
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void contextInitialized(ServletContextEvent event) {
try {
//기본 생성자 호출
applicationContext = new ApplicationContext();
//빌더 패턴(Builder Pattern) 객체 생성
String resource = "spms/dao/mybatis-config.xml";
//getResourceAsStream() : 자바 클래스 경로(CLASSPATH)에 있는 파일의 입력 스트림 얻음
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//ApplicationContext 클래스에 SqlSessionFactory 객체 등록
applicationContext.addBean("sqlSessionFactory", sqlSessionFactory);
//DB 커넥션 객체 준비
ServletContext sc = event.getServletContext();
//web.xml 파일로부터 프로퍼티 파일 이름과 경로 정보 읽어옴
String propertiesPath = sc.getRealPath(sc.getInitParameter("contextConfigLocation"));
//applicationContext = new ApplicationContext(propertiesPath);
//프로퍼티 파일 내용에 따라 객체 생성
applicationContext.prepareObjectsByProperties(propertiesPath);
//@Component 어노테이션이 붙은 클래스 찾아 객체 생성
applicationContext.prepareObjectsByAnnotation("");
//ApplicationContext 클래스에서 관리하는 객체들 의존 객체 주입
applicationContext.injectDependency();
} catch(Throwable e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent event) {}
}
기존 코드는 프로퍼티와 어노테이션 만으로 객체를 생성했기 때문에 ApplicationContext 클래스가 모두 처리하였다. 다음은 변경하기 전의 코드이다.
//DB 커넥션 객체 준비
ServletContext sc = event.getServletContext();
//web.xml 파일로부터 프로퍼티 파일 이름과 경로 정보 읽어옴
String propertiesPath = sc.getRealPath(sc.getInitParameter("contextConfigLocation"));
applicationContext = new ApplicationContext(propertiesPath);
ApplicationContext 클래스의 생성자에 프로퍼티 파일의 경로를 넘겨주면 프로퍼티 파일에 등록된 객체뿐만 아니라, @Component 어노테이션이 붙은 클래스를 찾아서 객체를 생성했다.
- ApplicationContext의 기본 생성자 호출
SqlSessionFactory 객체를 별도로 생성해서 등록해야 하기 때문에 기존의 방식처럼 객체 생성과 의존 객체 주입을 생성자에게 일괄처리 할 수 없다. 따라서 ApplicationContext 객체를 생성할 때 기본 생성자를 호출하도록 코드를 변경하였다.
//기본 생성자 호출
applicationContext = new ApplicationContext();
- SqlSessionFactory 객체 생성과 빌더 패턴
SqlSessionFactory 객체는 new 연산자로 객체를 생성할 수 없다. 조금 복잡한 방식으로 객체를 생성한다. 다음 그림은 SqlSessionFactory 객체를 만드는 과정을 보여주고 있다(그림 1).
앞의 그림을 보면 꼭 건설사가 공장을 짓는 것과 비슷하다. 공장 설계도를 작성하여 건설사에 넘기면, 건설사는 설계도에 따라 공장을 짓는다. 간단한 건물은 외부 인력을 동원하여 직접 지을 수가 있지만, 공장과 같은 복잡한 건물은 외부 전문가에게 맡겨야 한다. 프로그래밍 세계도 똑같다. 단순한 객체는 new 연산자를 사용하여 직접 생성하지만 복잡한 객체는 전문가를 통해 생성하도록 설계한다. 이런 식의 객체 생성 패턴을 '빌더 패턴(Builder Pattern)'이라 부른다.
SqlSessionFactory 클래스도 이름에서 알 수 있듯이 SqlSession 객체를 만드는 공장 객체이다. 이 객체를 만들려면 SqlSessionFactoryBuilder 클래스를 이용해야 한다. 앞의 코드와 같이 SqlSessionFactoryBuilder 클래스의 build() 메서드를 호출해야만 SqlSessionFactory 객체를 생성할 수 있다.
//빌더 패턴(Builder Pattern) 객체 생성
String resource = "spms/dao/mybatis-config.xml";
//getResourceAsStream() : 자바 클래스 경로(CLASSPATH)에 있는 파일의 입력 스트림 얻음
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
mybatis 설정 파일 'mybatis-config.xml'은 SqlSessionFactory 객체를 생성할 때 사용할 설계도면이다. build() 메서드의 매개변수 값으로 이 파일의 입력 스트림을 넘겨줘야 한다. mybatis 설정 파일은 보통 자바 클래스 경로(CLASSPATH)에 둔다. 이 파일의 입력 스트림을 얻기 위해 mybatis에서 제공하는 Resources 클래스를 사용하였다. Resources 클래스의 getResourceAsStream() 메서드를 이용하면 자바 클래스 경로에 있는 파일의 입력 스트림을 손쉽게 얻을 수 있다.
- SqlSessionFactory 객체 등록
SqlSessionFactory 객체를 생성했으면 ApplicationContext 클래스에 등록해야 한다. 그래야만 DAO에 주입할 수 있다. ApplicationContext 클래스에 추가된 addBean() 메서드를 호출하여 SqlSessionFactory 객체를 등록하였다.
//ApplicationContext 클래스에 SqlSessionFactory 객체 등록
applicationContext.addBean("sqlSessionFactory", sqlSessionFactory);
- 프로퍼티 파일의 경로 알아내기
프로퍼티 파일(application-context.properties)의 경로를 알아내는 것은 기존 코드와 같다.
//DB 커넥션 객체 준비
ServletContext sc = event.getServletContext();
//web.xml 파일로부터 프로퍼티 파일 이름과 경로 정보 읽어옴
String propertiesPath = sc.getRealPath(sc.getInitParameter("contextConfigLocation"));
- 프로퍼티 파일과 어노테이션에 설정된 대로 객체 생성
이제 프로퍼티 파일의 내용에 따라 객체를 생성하도록 ApplicationContext 클래스에 지시한다.
//프로퍼티 파일 내용에 따라 객체 생성
applicationContext.prepareObjectsByProperties(propertiesPath);
@Component 어노테이션이 붙은 클래스를 찾아 객체를 생성한다.
//@Component 어노테이션이 붙은 클래스 찾아 객체 생성
applicationContext.prepareObjectsByAnnotation("");
- 의존 객체 주입
마지막으로 ApplicationContext 클래스에서 관리하는 객체들을 조사하여 의존 객체를 주입한다.
//ApplicationContext 클래스에서 관리하는 객체들 의존 객체 주입
applicationContext.injectDependency();
7. mybatis 설정 파일 준비
SqlSessionFactoryBuilder 객체가 SqlSessionFactory 객체를 생성하려면 설계 도면이 필요하다. 즉 mybatis 설정 파일이 있어야 한다. 이제 mybatis를 사용하기 위한 마지막 단계로 mybatis 설정 파일을 작성해 본다. mybatis 설정 파일은 DB 커넥션을 생성하는 데이터소스에 대한 정보와 트랜잭션 관리자, mybatis 동작을 제어하는 환경값, SQL문이 저장된 맵퍼 파일의 경로 등의 정보를 포함하고 있다.
spms.dao 패키지에 mybatis-config.xml 파일을 생성한 뒤 다음과 같이 편집한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="spms/dao/db.properties"/>
<typeAliases>
<typeAlias type="spms.vo.Project" alias="project"/>
<typeAlias type="spms.vo.Member" alias="member"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="spms/dao/MySqlProjectDao.xml"/>
</mappers>
</configuration>
mybatis 설정 파일에 대한 자세한 설명은 다음 강의에서 설명한다.
8. db.properties 파일 작성
데이터베이스 접속 정보를 담은 프로퍼티 파일을 작성한다. 이 프로퍼티 파일은 mybatis 설정 파일에서 참조한다.
spms.dao 패키지에 db.properties 파일을 생성하여 다음과 같이 편집한다.
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/studydb
username=study
password=study
DBMS에 대한 정보를 별도의 파일로 관리하면 유지 보수에 좋다. 웹 애플리케이션을 배치할 때 사용할 DBMS에 맞추어 이 파일만 교체하거나 변경하면 된다.
톰캣 서버를 재시작한 뒤 웹 브라우저에서 http://localhost:9999/web07/project/list.do 페이지를 요청한다. 프로젝트 목록에서 신규 프로젝트 등록, 변경, 삭제를 테스트한다. 잘 동작한다.
기존 소스와 비교해 보면 MySqlProjectDao 클래스에서 어떤 JDBC 코드도 발견할 수 없다. 데이터베이스와 관련된 작업은 모두 mybatis에서 처리하기 때문이다. 개발자는 단지 DAO에서 사용할 SQL문 작성에만 집중하면 된다. 어쩌면 이 SQL문도 데이터베이스 전문가가 있다면 그에게 맡겨도 될 것이다. 이것이 mybatis 프레임워크를 사용하는 이유이다.
참고도서 : https://freelec.co.kr/book/1674/
[열혈강의] 자바 웹 개발 워크북
[열혈강의] 자바 웹 개발 워크북
freelec.co.kr
'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글
108. SQL 맵퍼 파일 (2) (0) | 2022.09.03 |
---|---|
107. SQL 맵퍼 파일 (1) (0) | 2022.09.01 |
105. mybatis 적용 (3) (1) | 2022.08.30 |
104. mybatis 적용 (2) (0) | 2022.08.29 |
103. mybatis 적용 (1) (0) | 2022.08.28 |
댓글