organize/스프링

스프링 웹 프로젝트 3

001cloudid 2024. 12. 29. 15:34
728x90

MyBatis와 스프링 연동

 

연동에 앞서 MyBatis란?

  • SQL Mapping 프레임 워크
    SQL과 Object 간의 관계를 매핑해주는 역할
    JDBC 코드에 비해 처리하는 부분이 간결해지고, close 처리를 지원
    ※ JPA와는 다름. JPA(RDBMS -> 객체지향에 접목). MyBatis는 SQL, 객체지향 매핑하는 역할
  • Spring에서의 사용
    스프링은 MyBatis와의 연결을 위한 mybatis-spring 라이브러리를 이용해서 연동 처리

 

MyBatis 세팅

기본적으로 dataSource 설정 필요

pom.xml 라이브러리 추가

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>

위의 라이브러리만 추가해도 개발이 가능하지만, 스프링과 연동하면 더 좋아짐. MyBatis Spring 라이브러리도 추가

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.2</version>
</dependency>

추가적인 설정이 필요 spring-jdbc, spring-tx

			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

SqlSeesionFactory의설정

root-context.xml에 MyBatis설정

MyBatis의 핵심 객체는 SqlSessionFactory 타입의 객체

SqlSessionFactoryBean은 내부적으로 MyBatis의 SqlSessionFactory를 생성

	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dateSource"></property>
	</bean>

 

동작 확인(매우 중요한 설정이므로 하나씩 확인-동작해주는 것을 추천)

DataSourceTests에 아래 코드를 추가

package org.zerock.persistence;

(...생략...)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class DataSourceTests {

(...생략...)

	@Autowired
	private SqlSessionFactory sqlSessionFactory;

(...생략...)

	@Test
	public void testConnection2() {
		try (SqlSession session = sqlSessionFactory.openSession(); Connection connection = session.getConnection()) {
			log.info(session);
            log.info(connection);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
		}
	}
    
}

AutoClose하기 때문에 close를 해주지 않아도 됨


스프링 연동 처리 및 연동 테스트

src/main/java 폴더 안에 org.zerock.mapper 패키지를 생성 → TimeMapper 인터페이스

package org.zerock.mapper;

import org.apache.ibatis.annotations.Select;

public interface TimeMapper {
	
	@Select("select sysdate from dual") // 주의 ;(세미콜론)이 없어야함
	public String getTime();
	
}

Mapper 설정 root-context.xml에서 Namespaces에서 Mybatis-spring을 체크

체크하고 Source를 확인하면 코드가 자동으로 추가됨

자동 완성 기능이 됨

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		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">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
	
	<bean id="hikariConnfig" class="com.zaxxer.hikari.HikariConfig">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:XE"></property>
		<property name="username" value="book_ex"></property>
		<property name="password" value="book_ex"></property>
	</bean>
	
	<bean id="dateSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
		<constructor-arg ref="hikariConnfig" />
	</bean>
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dateSource"></property>
	</bean>
	
	<mybatis-spring:scan base-package="org.zerock.mapper"/>
		
	<context:component-scan base-package="org.zerock.sample"></context:component-scan>
		
</beans>

이 과정까지하면 연동 처리가 완료

 

테스트 진행

src/test/java 폴더의 org.zerock.persistence 패키지 안에 TimeMapperTests클래스를 생성

package org.zerock.persistence;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.zerock.mapper.TimeMapper;

import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class TimeMapperTests {
	
	@Autowired
	private TimeMapper timeMapper;
	
	@Test
	public void testTime1() {
		
		timeMapper.getTime(); // 호출
	}

}

package org.zerock.persistence;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.zerock.mapper.TimeMapper;

import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class TimeMapperTests {
	
	@Autowired
	private TimeMapper timeMapper;
	
	@Test
	public void testTime1() {
		
//		timeMapper.getTime(); // 호출
		log.info(timeMapper.getTime());
		
	}

}


XML Mapper 설정

spring-test를 이용해서 테스트 코드 작성 시 sql이 길어지면 관리가 힘들어짐. XML Mapper와 Mapper 인터페이스를 사용

XML 파일은 src/main/java 폴더 mapper 패키지에 생성하거나 src/main/resources 폴더에 mapper 폴더를 만들고 생성해도 됨

단, src/main/resources 폴더에 만들때 폴더를 만들 때 하나하나씩 만들어야함

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">

↑ XML 문서를 만들면 dtd -> 자동완성기능 

위의 코드를 작성하면 자동완성기능이 되며, 아래와 같이 쿼리를 작성

<?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="org.zerock.mapper.TimeMapper">  <!-- namespace는 인터페이스와 동일하게 -->
	<select id="getTime2"> <!-- getTime2에는 sql이 없음 -> mybatis는 xml에서 찾아 sql을 실행  -->
		select sysdate from dual
	</select>
</mapper>

현재 동작 확인

TimeMapperTests에 코드 추가

	@Test
	public void testTime2() {
		
		log.info(timeMapper.getTime2());
	}

sql은 실행되었으나 처리를 어떻게 해야할지 모르겠다는 의미의 에러가 발생

select의 경우 반환타입이 있어야함

TimeMapper.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="org.zerock.mapper.TimeMapper">
	<select id="getTime2" resultType="string"> <!-- getTime2에는 sql이 없음 -> mybatis는 xml에서 찾아 sql을 실행  -->
		select sysdate from dual
	</select>
</mapper>

정상 동작

mybatis 연동, spring-mybatis연동, xml처리까지 완료


log4jdbc-log4j2 설정

※ MyBatis는 내부적으로 PreparedStatement를 이용하기 때문에 좀 더 쉽게 SQL의 로그를 보기 위한 설정 → DB 버전에 조심해야함. 안될 경우 순수 jdbc로 로그를 찍어야함

 

순서 : 라이브러리 추가 → 프로퍼티 파일 추가 → DataSource 설정 변경

라이브러리 추가

		<!-- 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.Properties
0.00MB

 

이 파일을 src/main/resources에 추가 테스트할 때 불안해서 저자는 src/test/resources에도 함께 추가하는 것을 추천함

 

DataSource 설정 변경

root-context.xml에서

	<bean id="hikariConnfig" class="com.zaxxer.hikari.HikariConfig">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:XE"></property>
		<property name="username" value="book_ex"></property>
		<property name="password" value="book_ex"></property>
	</bean>

이 부분을 수정

	<bean id="hikariConnfig" class="com.zaxxer.hikari.HikariConfig">
		<property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
		<property name="jdbcUrl" value="jdbc:log4jdbc:oracle:thin:@localhost:1521:XE"></property>
		<property name="username" value="book_ex"></property>
		<property name="password" value="book_ex"></property>
	</bean>

이 상태에서 JUnit 테스트

콘솔창 내용을 복사 붙여넣기

|----------------------|
|sysdate               |
|----------------------|
|2024-12-29 15:31:58.0 |
|----------------------|

INFO : jdbc.resultset - 1. ResultSet.next() returned false
INFO : jdbc.resultset - 1. ResultSet.close() returned void
INFO : jdbc.audit - 1. Connection.getMetaData() returned oracle.jdbc.driver.OracleDatabaseMetaData@5b12012e
INFO : jdbc.audit - 1. PreparedStatement.close() returned 
INFO : jdbc.audit - 1. Connection.clearWarnings() returned 
INFO : org.zerock.persistence.TimeMapperTests - 2024-12-29 15:31:58.0
INFO : com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated...
INFO : jdbc.connection - 1. Connection closed
INFO : jdbc.audit - 1. Connection.close() returned 
INFO : jdbc.connection - 2. Connection closed
INFO : jdbc.audit - 2. Connection.close() returned 
INFO : jdbc.connection - 3. Connection closed
INFO : jdbc.audit - 3. Connection.close() returned 
INFO : jdbc.connection - 4. Connection closed
INFO : jdbc.audit - 4. Connection.close() returned 
INFO : jdbc.connection - 5. Connection closed
INFO : jdbc.audit - 5. Connection.close() returned 
INFO : jdbc.connection - 6. Connection closed
INFO : jdbc.audit - 6. Connection.close() returned 
INFO : jdbc.connection - 7. Connection closed
INFO : jdbc.audit - 7. Connection.close() returned 
INFO : jdbc.connection - 8. Connection closed
INFO : jdbc.audit - 8. Connection.close() returned 
INFO : jdbc.connection - 9. Connection closed
INFO : jdbc.audit - 9. Connection.close() returned 
INFO : jdbc.connection - 10. Connection closed
INFO : jdbc.audit - 10. Connection.close() returned 
INFO : com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.

 

 

이렇게 동작하지 않는다면

설정 전 동작하는지 확인하고 동작 확인이 되는데 안된다면 DB나 JDBC 드라이버의 지원이 안됨.

 

728x90

'organize > 스프링' 카테고리의 다른 글

스프링 웹 프로젝트 5  (0) 2024.12.31
스프링 웹 프로젝트 4  (0) 2024.12.30
스프링 웹 프로젝트 2  (0) 2024.12.28
스프링 웹 프로젝트 1  (3) 2024.12.27
웹 시큐리티  (0) 2024.10.05