본문 바로가기

STUDY/Spring

[Spring] Spring, MariaDB, MyBatis 연동

* 2021.02.10 작성 기준

 

★ Mybatis

- 자바 퍼시스턴스 프레임 워크의 하나로 XML 서술자나 Annotation을 사용하여 저장

- 프로시저나 SQL문으로 객체들을 연결

 

 

1. Dependency 추가

- pom.xml 수정 - <dependencies> ~ </dependencies> 사이에 작성

- MariaDB, MyBatis 관련 dependency 추가

<!-- DB -->
        <!-- Maria DB -->
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <version>2.0.3</version>
        </dependency>
 
        <!-- DBCP 데이터베이스 풀 커넥션 -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
 
        <!-- Spring JDBC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.9.RELEASE</version>
        </dependency>
 
        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>
 
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>
        
        <!-- Mybatis log -->
        <!-- https://mvnrepository.com/artifact/org.bgee.log4jdbc-log4j2/log4jdbc-log4j2-jdbc4.1 -->
        <dependency>
            <groupId>org.bgee.log4jdbc-log4j2</groupId>
            <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
            <version>1.16</version>
        </dependency>
 

* log4jdbc-log4j2-jdbc4.1은 로그를 남기기 위한 라이브러리

 

2. root-context.xml 수정 - 웹 이외의 부분을 세팅하기 위해 존재하는 곳

<bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"
            value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
        <property name="url"
            value="jdbc:log4jdbc:mariadb://127.0.0.1:3306/theater" />
        <property name="username" value="root" />
        <property name="password" value="devfunpj" />
    </bean>
 
 
    <bean id="sqlSessionFactory"
        class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation"
            value="classpath:/mybatis/mybatis-config.xml"></property>
        <property name="mapperLocations"
            value="classpath*:/mybatis/sql/*.xml"></property>
    </bean>
 
    <bean id="sqlSession"
        class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory"
            ref="sqlSessionFactory"></constructor-arg>
    </bean>
 
    <!-- <mybatis-spring:scan base-package="com.dev.dao" /> -->
    <context:component-scan
        base-package="com.dev.dao"></context:component-scan>
    <context:component-scan
        base-package="com.dev.service"></context:component-scan>
 

* datasource: DB연결 정보, "로컬주소/스키마"로 이루어져있고, ID와 PW 입력

ex) MyBatis, MariaDB

* SqlSessionFactoryBean: MariaDB 설정기능을 사용하도록 세팅하고 mapperLocation(SQL문)을 mybatis/sql 경로에 있는 xml파일로 한다고 명시

* SqlSessionTemplate: 트랜잭션 관리와 Thread 처리, DB연결 및 종료를 관리하는 영역

* spring-jdbc 모듈에 있는 클래스(org.springframework.jdbc.datasource.DriverManagerDataSource)를 이용하여 JDBC 드라이버를 통해 MySQL 서버에 접속할 수 있게 함

 


 

 

 

◆ The prefix "context" for element "context:component-scan" is not bound 오류 발생 시

- <bean xmlns= ~> 사이에 아래 소스코드 삽입

xmlns:context="http://www.springframework.org/schema/context"
 
 

 

◆ cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'context:component-scan' 오류 발생 시

- <bean xmlns= ~> 사이에 아래 소스코드 삽입

xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 

 

 

 


 

 

◆ 분명 폴더를 생성했는데 패키지 구조로 생성될 때 폴더로 변경하기 위한 방법

 

[프로젝트 우클릭] - [Build Path] - [Configure Build Path...]

해당 폴더의 [Excluded 클릭] - [Edit...]

Inclusion and Exclusion Patterns: Build Path에 지정된 내역 중 Source folder에 포함/불포함 시킬 패턴 구조를 지정

[Exclusion patterns:] - [Add...]

source folder에서 제외할 파일 패턴을 지정

*나 ?와 같은 와일드 카드도 사용이 가능하므로, 모두 제외시킬 수 있도록 ** 패턴을 사용

[**] - [OK]

 

 

폴더로 변경됨을 확인 가능


 

 

 

3. MyBatis 설정 파일 생성

- mybatis-config.xml은 [resources] - [mybatis]에 존재해야 함

- sql을 담고 있는 xml 파일인 test.xml은 mybatis/sql 경로 안에 존재해야 함

* 아래와 같은 구조로 파일을 생성

1) [resources] - [mybatis] - [sql] - [test.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
<mapper namespace="com.dev.mybatis.sql.test">
 
    <select id="selectMovie" resultType="movieVO">
        SELECT MOVIE_NAME, DIRECTOR, TYPE FROM MOVIE
    </select>
    
</mapper>
 

 

2) [resources] - [mybatis] - [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>
    <typeAliases>
        <typeAlias type="com.dev.vo.MovieVO" alias="movieVO" />
    </typeAliases>
 
 
</configuration>
 

* VO: VO를 선언하여 mybatis/sql/하위의 쿼리들을 실행할 때 resultType, parameterType에 풀 패키지명을 쓰지 않고 선언한 alias의 이름만 사용하여 VO를 주고 받을 수 있도록 해줌 -> 별칭 개념

com.dev.vo.MovieVO를 매번 쓰지 않고 MovieVo로 사용 가능

 

3) [resources] - [logback.xml]

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    
    <!-- log4jdbc-log4j2 -->
    <logger name="jdbc.sqlonly"     level="DEBUG" />
    <logger name="jdbc.sqltiming"     level="INFO" />
    <logger name="jdbc.audit"         level="WARN" />
    <logger name="jdbc.resultset"     level="ERROR" />
    <logger name="jdbc.resultsettable" level="ERROR" />
    <logger name="jdbc.connection"     level="INFO" />
 
</configuration>
 

* logger 설정

 

4) [resources] - [log4jdbc.log4j2.properties]

* properties 파일은 Untitled Text File로 생성

[Ctrl] + [S] 로 저장 위치 설정

log4jdbc.drivers=org.mariadb.jdbc.Driver
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
log4jdbc.dump.sql.maxlinelength=0
 

* log 확인을 위한 설정

 

5) [resources] - [log4j.xml]

- Root Logger 부분의 value = "warn"을 "info"로 수정

	<!-- Root Logger -->
	<root>
		<priority value="info" />
		<appender-ref ref="console" />
	</root>
 

 

 

 

 


 

 

 

◆ Cannot find DTD 'log4j.dtd'. Create the DTD file or configure an XML catalog for this DTD. 오류 발생 시

log4j.xml 파일에서 DTD 파일의 경로를 웹의 절대 경로로 지정

<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
 

 

 

 


 

 

 

 

4. 데이터 조회/처리를 위한 JAVA 코드 작성

1) [java] - [com.dev.dao] - [MovieDAO.java]

* interface 파일 생성

package com.dev.dao;
import java.util.List;
import com.dev.vo.MovieVO;

public interface MovieDAO {
	 public List<MovieVO> selectMovie() throws Exception;
}
 

* MovieVO를 담고 있는 리스트를 가지는 함수가 있는 인터페이스 작성

 

2) [java] - [com.dev.dao] - [MovieDAOImpl.java]

* Class 생성 - implemented

 

package com.dev.dao;

import java.util.List;
import javax.inject.Inject;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
 
import com.dev.vo.MovieVO;

@Repository
public class MovieDAOImpl implements MovieDAO {
	 @Inject
	 private SqlSession sqlSession;
	 private static final String Namespace = "com.dev.mybatis.sql.test";
	    
	 @Override
	 public List<MovieVO> selectMovie() throws Exception {
	 
	     return sqlSession.selectList(Namespace+".selectMovie");
	 }
}
 

* Sql Session을 통해 등록된 SQL 쿼리문을 실행하려 List를 return

 

3) [java] - [com.dev.service] - [MovieService.java]

package com.dev.service;

import java.util.List;
import com.dev.vo.MovieVO;

public interface MovieService {
	public List<MovieVO> selectMovie() throws Exception;
}
 

* [service]: 비지니스 로직을 작성하는 곳, DB처리 시 많이 이용됨

 

4) [java] - [com.dev.service] - [MovieServiceImpl.java]

package com.dev.service;

import java.util.List;
import javax.inject.Inject;
import org.springframework.stereotype.Service;
 
import com.dev.dao.MovieDAO;
import com.dev.vo.MovieVO;

@Service
public class MovieServiceImpl implements MovieService {
	 @Inject
	 private MovieDAO dao;
	    
	 @Override
	 public List<MovieVO> selectMovie() throws Exception {
	 
	     return dao.selectMovie();
	 }
}
 

* MovieDAO 객체를 의존 주입(DI, Dependency Injection)

- DI: 객체 자체가 아니라 Framework에 의해 객체의 의존성이 주입되는 설계 패턴

 

5) [java] - [com.dev.projectweb] - [HomeController.java]

package com.dev.projectweb;

import java.util.List;
import java.util.Locale;

import javax.inject.Inject;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.dev.vo.MovieVO;
import com.dev.service.MovieService;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
    @Inject
    private MovieService service;

	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) throws Exception {
		
        logger.info("home");
        
        List<MovieVO> movieList = service.selectMovie();
        
        model.addAttribute("movieList", movieList);
 
        return "home";
	}
	
}
 

* @RequestMapping: 호출하기 위한 URL의 path

* @Controller: service에서 selectMovie를 호출하여 model에 담은 후 해당 내용을 화면으로 전달

* return "home": home.jsp 화면으로 전달한다는 내용

 

6) [java] - [com.dev.vo] - [MovieVO.java]

package com.dev.vo;

public class MovieVO {
	private String movie_name;
	private String director;
	private String type;
	
	public String getMovie_name() {
		return movie_name;
	}
	public void setMovie_name(String movie_name) {
		this.movie_name = movie_name;
	}
	public String getDirector() {
		return director;
	}
	public void setDirector(String director) {
		this.director = director;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
}
 

* DB 테이블의 column명과 동일하게 멤버 변수를 선언

* get, set을 통해 멤버 변수에 접근

 

5. 화면 관련 소스 작성 (home.jsp)

- home.jsp를 호출한다는 정보는 servlet-context.xml파일에서 확인 가능

- Views에 있는 jsp 파일로 호출하겠다는 의미

 

- home.jsp 파일 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<body>
    <h1>Hello world!</h1>
 
    <table>
        <thead>
            <tr>
                <th>영화이름</th>
                <th>감독</th>
                <th>장르</th>
            </tr>
        </thead>
        <tbody>
            <c:forEach items="${movieList}" var="movie">
                <tr>
                    <td>${movie.movie_name}</td>
                    <td>${movie.director}</td>
                    <td>${movie.type}</td>
                </tr>
            </c:forEach>
        </tbody>
    </table>
 
 
</body>
</html>
 

* movieList를 받아서 c:forEach문으로 조회된 결과를 출력

 

6. Tomcat 세팅 변경 (localhost:8080/프로젝트명 -> localhost:8080)

- 구동하려는 Tomcat 서버 더블클릭

- 하단의 [Modules] 클릭

 

- Path를 변경하기 위해 [Edit...] 클릭

- Path에서 "/프로젝트명" 을 "/" 으로 수정

 

 

7. localhost:8080 으로 접속