MyBatis 연동 (Maven 기반 Spring MVC)

suah·2025년 4월 18일

Maven: 프로젝트 빌드 도구

설치하기

참고) https://mvnrepository.com/ 에서 필요한 라이브러리 검색하면 버전, 작성법 나옴

odjbc 등록하기

방법 1
1. Maven CLI 설치
2. 로컬에 직접 ojdbc를 Maven 라이브러리로 등록

mvn install:install-file \
  -Dfile=ojdbc11.jar \
  -DgroupId=com.oracle.database.jdbc \
  -DartifactId=ojdbc11 \
  -Dversion=21.5.0.0 \
  -Dpackaging=jar

방법 2
1. odjbc11.jar 파일을 다운로드해서 프로젝트의 src/main/resources/lib에 붙여넣기
2. 해당 jar 파일 마우스 우클릭 > Build Path > Add to Build Path

pom.xml

<dependencies>
  <!-- Spring 관련 -->
  <dependency>
 	<groupId>org.springframework</groupId>
  	<artifactId>spring-context</artifactId>	<!-- IoC 컨테이너 제공. Bean 관리, 읜존성 주입, AOP 등 -->
  	<version>6.1.3</version>
  </dependency>
  <dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId> <!-- DispatcherServlet, @Controller, ViewResolver -->
	<version>6.1.4</version>
  </dependency>
  <dependency>
  	<groupId>org.springframework</groupId>
  	<artifactId>spring-jdbc</artifactId> <!-- DataSource 설정, jdbcTemplate 제공 -->
  	<version>6.1.3</version>
  </dependency>
  <!-- Jakarta EE -->
  <dependency>
  	<groupId>jakarta.servlet</groupId>
  	<artifactId>jakarta.servlet-api</artifactId> <!-- Serlvet 기능 위한 API -->
  	<version>6.0.0</version>
  	<scope>provided</scope> <!-- provided인 이유: 컨테이너(Tomcat)에서 제공하므로 빌드 시만 필요 -->
  </dependency>
  <dependency>
	<groupId>jakarta.servlet.jsp</groupId>
	<artifactId>jakarta.servlet.jsp-api</artifactId> <!-- JSP 관련 API -->
	<version>3.0.0</version>
	<scope>provided</scope>
  </dependency>
  <dependency>
	<groupId>jakarta.servlet.jsp.jstl</groupId>
	<artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <!-- JSTL API. <c:forEach>, <c:if> 같은 JSTL 태그 사용할 수 있게 함 -->
	<version>3.0.0</version>
  </dependency>
  <dependency>
	<groupId>org.glassfish.web</groupId>
	<artifactId>jakarta.servlet.jsp.jstl</artifactId> <!-- 위 API에 대한 실제 구현체. JSTL 태그가 실제 동작하도록 하는 역할 -->
	<version>3.0.1</version>
  </dependency>
  <!-- DB 및 커넥션 풀 -->
  <dependency>
	<groupId>com.zaxxer</groupId>
	<artifactId>HikariCP</artifactId> <!-- 빠르고 가벼운 DB 커넥션 풀 -->
	<version>5.1.0</version>
  </dependency>
  <dependency>
 	<groupId>com.oracle.database.jdbc</groupId>
  	<artifactId>ojdbc11</artifactId> <!-- Oracle DB용 JDBC 드라이버 -->
  	<version>21.5.0.0</version>
  </dependency>
  <!-- MyBatis 관련 -->
  <dependency>
    <groupId>org.mybatis</groupId>
  	<artifactId>mybatis</artifactId> <!-- SQL Mapper 프레임워크. XML이나 어노테이션 기반으로 SQL 작성하고, 객체와 매핑시켜줌 -->
  	<version>3.5.17</version>
  </dependency>
  <dependency>
  	<groupId>org.mybatis</groupId>
  	<artifactId>mybatis-spring</artifactId> <!-- MyBatis와 Spring 연동하기 위한 어댑터. SqlSessionTemplate 등을 통해 스프링 빈으로 MyBatis 사용할 수 있게 해줌 -->
  	<version>3.0.3</version>
  </dependency>
</dependencies>

회원 기능 실습하기

설정 클래스

  • WebAppInitializer.java: 웹 애플리케이션이 시작될 때 실행되는 초기 설정 클래스
  • MyBatisConfig.java: DB 연결, MyBatis 설정, Mapper 연결 등 DB 관련 전반을 설정하는 클래스
  • AppConfig.java: Spring MVC 웹 설정을 담당하는 클래스. 컨트롤러 스캔과 View 설정 등을 포함

Mapper 인터페이스

  • XML 기반: SQL을 .xml 파일에 정의 -> 유지보수 편리, 복잡한 쿼리에 유리
  • 애너테이션 기반: SQL을 자바 코드에 직접 작성 -> 간단한 쿼리엔 빠르고 간결

설정 클래스

- WebAppInitializer.java

  • Root Context: 애플리케이션 전역 설정
    - MyBatisConfig를 등록해서 DB 설정을 준비
    - ContextLoaderListener로 rootContext를 서버에 등록

  • Web Context: 웹 관련 설정, AppConfig 등록

  • 톰캣이 실행되면 DispatcherServlet을 메모리에 올리고 모든 요청(/)을 DispatcherServlet이 받는다.

public class WebAppInitializer implements WebApplicationInitializer {
	@Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // Root Context (MyBatis, Service)
		AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
		rootContext.register(MyBatisConfig.class);
		servletContext.addListener(new ContextLoaderListener(rootContext));
		
		// Web Context (Spring MVC)
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(AppConfig.class);

		// DispatcherServlet
        DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", dispatcherServlet);
        dispatcher.setLoadOnStartup(1); // 값이 1 이상이면 톰캣 실행 시 DispatcherServlet을 미리 메모리에 로드
        dispatcher.addMapping("/");
    }

}

- MyBatisConfig.java

  • dataSource: Oracle DP에 연결할 수 있도록 HikariCP를 이용해 커넥션 풀 설정
  • sqlSessionFactory
    - MyBatis의 핵심인 SqlSessionFactory 생성
    - mapper/*.xml의 SQL 파일을 매핑
    - MapUnderscoreToCamelCase(true): DB 컬럼명이 user_id면 Java에서는 userId로 자동 매핑
  • sqlSessionTemplate
    - MyBatis + Spring 연동 핵심 객체
    - MyBatis의 SqlSession을 Spring에서 사용할 수 있게 해주는 래퍼
@Configuration
@MapperScan(basePackages = "mapper") // mapper 인터페이스 위치
public class MyBatisConfig {
	
	@Bean
	public DataSource dataSource() {
		HikariDataSource ds = new HikariDataSource();
		ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
	    ds.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:xe");
	    ds.setUsername("c##scott");
	    ds.setPassword("tiger");
	    return ds;
	}
	
	@Bean
	public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
		SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
	    factoryBean.setDataSource(dataSource);
	    // factoryBean.setTypeAliasesPackage("com.spring.ex01"); // vo 패키지
	    factoryBean.setMapperLocations(
	    			new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml")
	    		);
	    factoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
	    return (SqlSessionFactory) factoryBean.getObject();
	}
	
	@Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
	
}

- AppConfig.java

  • @EnableWebMvc: Spring MVC 활성화
  • @ComponentScan: com.spring.ex01 패키지 안에서 @Controller 등을 찾아 @Bean으로 등록
  • viewResolver: .jsp 파일을 어디서 찾을지 지정하는 뷰 리졸버 설정
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="com.spring.ex01") // controller가 있는 패키지
public class AppConfig {
	@Bean
	public InternalResourceViewResolver viewResolver() {
		InternalResourceViewResolver resolver = new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/views/");
		resolver.setSuffix(".jsp");
		return resolver;
	}
}

Mapper 인터페이스

- XML 기반

  • namespace로 해당 Mapper 인터페이스(패키지 포함) 지정
  • resultMap의 id를 select의 resultMap으로 지정해 연결

MemberMapper.java

@Mapper
public interface MemberMapper {
	List<MemberVO> selectAllMemberList();
}

member.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.MemberMapper">
	<resultMap id="memResult" type="com.spring.ex01.MemberVO">
		<result property="id" column="id" />
        <result property="pwd" column="pwd" />
        <result property="name" column="name" />
        <result property="email" column="email" />
        <result property="joinDate" column="joinDate" />
	</resultMap>
	
	<select id="selectAllMemberList" resultMap="memResult">
    	<![CDATA[
        	select * from t_member	order by joinDate desc	 	
    	]]>
	</select>
</mapper>

- 애너테이션 기반

MemberMapper2.java

@Mapper
public interface MemberMapper2 {
	@Select("SELECT * FROM t_member ORDER BY joinDate DESC")
    List<MemberVO> selectAllMemberList();
}

MemberController.java

@Controller
public class MemberController {
	private final MemberMapper memberMapper;

    public MemberController(MemberMapper memberMapper) {
        this.memberMapper = memberMapper;
    }

    @GetMapping("/members1")
    public String listMembers(Model model) {
        List<MemberVO> membersList = memberMapper.selectAllMemberList();
        model.addAttribute("membersList", membersList);
        return "test01/listMembers"; // => /WEB-INF/views/test01/listMembers.jsp
    }
}
profile
IT developer

0개의 댓글