Spring의 DB연결 프레임워크 (conn 관리와 MyBatis)

bethe·2022년 9월 1일
0

Springboot

목록 보기
26/46

1. Database 연결 과정

  1. conn : DB와 연결. 클라이언트가 서버에 연결할 때의 req, resp와 역할이 유사하다. (모델에는 DAO 뿐만이 아니라 Service도 있어야 함. 트랜잭션 관리를 해야 하기 때문)
  2. 쿼리 작성
  3. 쿼리 전송(PreparedStatement사용<-Buffer가 있음을 알 수 있다. 왜냐면 문자열(쿼리)를 전송하기 때문)
  4. rs(ResultSet)로 결과를 받음
  5. 받은 Data를 Java Object로 변경(Entity, DTO 등)

2. Springboot의 connection 관리

여러 명이 Model(S-D-DB)에 접속하기 위해서는 여러 스레드가 있어야 하고, 스레드마다 커넥션을 가지고 접속을 하게 된다. 그러나 DB도 받을 수 있는 커넥션의 한계가 있다.

🌳→🌿 DB를 복제하여 분산처리
해결방안으로 DB 분산처리가 있는데 분산처리의 단점이 있다.
단점 1 : 분산처리시 DB끼리 동기화가 되어야 한다.

단점 2 : 특정 DB에서 데이터 변경시(10000->20000) 데이터를 응답하고 그 뒤 동기화가 실행되는데 동기화가 완료되기도 전에 새로운 요청이 와 미처 동기화되지 못한 데이터값 (10000)을 응답할 수 있다. (동기화시 시간차 발생)

👉 이러한 문제를 관리하기 위해 DB끼리의 트랜젝션 처리를 해야 한다.


Spring 프레임워크에서는 요청을 받을 때마다 conn을 만드는 동기적 방식(conn이 끝없이 만들어진다)이 아닌, 미리 DB가 처리할 수 있는 수의 conn 객체를 IOC 컨테이너에 만들어 놓는 방식을 사용한다.

conn 객체를 넘겨주는 시점 : 서버(아파치)의 8080port를 통과하고 문지기 필터를 통과한 뒤 Spring의 DS 진입 전에 이루어진다.
conn 객체 반환 시점 : DS를 빠져나올 때 이루어진다. (물론 Controller나 Service에서 conn 연결이 끊어지도록 관리할 수도 있다.)

Pooling 기술
클라이언트는 항상 두 가지 메모리 저장소 = 자신만의 두 가지 객체를 가진다 : request, conn
conn은 DS를 빠져나올 때 객체를 돌려주고 request는 아파치 서버에서 빠져나갈 때까지 존재한다는 차이점이 있지만, 사용자가 conn 사용이 끝나면 conn을 삭제하지 않고 반환받아 보관하여 재사용하고 request 또한 객체를 미리 생성해놓고 서버를 빠져나가기 전까지 계속 데이터를 유지하여 역할을 수행한다.
이렇게 Pool에 미리 객체를 만들어 놓고 사용하는 기법이라 하여 Pooling 기술이라 부른다.


3. Springboot의 Query 관리 (작성 및 전송) : MyBatis 프레임워크

1) MyBatis 라이브러리

dependencies {
	implementation group: 'javax.servlet', name: 'jstl', version: '1.2'
	implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.65'
	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'
	runtimeOnly 'com.oracle.database.jdbc:ojdbc8'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

라이브러리에 MyBattis 라이브러리를 추가한다.
'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'

2) MyBatisConfig파일 만들기

config 폴더에 만듦

package site.metacoding.red.config;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

@Configuration
@MapperScan(basePackages = "site.metacoding.red.domain")
public class MyBatisConfig {
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {

        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();

        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(
        		new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        return sessionFactory.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

config 설정파일(여기서는 MyBatisConfig파일)은 Mapping된 xml파일을 읽어 Java object로 new 설정해주는 파일이다.

@Configuration
Java의 설정 파일 위에 붙는 어노테이션.
@Configuration이 아닌 @Controller를 붙이면 DS가 관리하게 되므로 @Configuration을 사용해야 한다.

@MapperScan
Mapping xml파일을 스캔하는 어노테이션. basePackages의 경로에 있는 DAO와 xml의 쿼리문을 Mapping해주기 때문에 basePackages의 경로는 실제 DAO가 있는 패키지로 설정해주어야 한다.

classpath : Java에서 classpath는 라이브러리를 관리하는 모든 폴더를 다 찾는 역할을 한다. Spring에서 classpath는 (src/main/resources)이다.
classpath:mapper/*.xml으로 설정되었으므로 라이브러리를 관리하는 폴더 중 mapper에서 확장자가 xml인 파일만 스캔한다.


MyBatisConfig의 역할

DAO가 interface로 만들어 질 경우, interface이므로 new를 하지 못한다. 이 때 MyBatis문법으로 구현한다.
MyBatisConfig는 xml파일의 쿼리문을 구현할 객체를 만들어 new 한다. 이 때, 이 객체는 xml파일의 namespace경로에서 부모가 될 DAO를 읽고 이 부모를 상속한다. 이 객체 안에 xml의 쿼리문이 들어가는 것이다.

new된 DAO구현체는 IOC 컨테이너에 띄워진다.

요약 : xml을 보고 interface인 DAO의 구현체를 쿼리문에 따라 자동으로 만들어 new 하며 IOC 컨테이너에 띄운다.


3) mapper폴더에 쿼리문을 적을 .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="site.metacoding.red.domain.users.UsersDao">
	
	<select id="update">
		UPDATE users
		SET username = #{username},
		password = #{password},
		email = #{email}
		WHERE id = #{id}
	</select>
	
	<insert id="insert">
		INSERT INTO users(id, username, password, email, createdAt) 
		VALUES(users_seq.nextval, #{username}, #{password}, #{email}, sysdate)
	</insert>

	<select id="findById" resultType="site.metacoding.red.domain.users.Users">
		SELECT * FROM users WHERE id = #{id}
	</select>

	<select id="findAll" resultType="site.metacoding.red.domain.users.Users">
		SELECT * FROM users ORDER BY id DESC
	</select>
	
	<delete id="delete">
		DELETE FROM users WHERE id = #{id}
	</delete>
	
</mapper>

namespace="경로"
MyBatisConfig에서 부모로 상속할 DAO의 경로를 적는 곳이자 xml 쿼리문이 적용되는 DAO의 경로를 적는 곳.

id=" "
: DAO의 함수명과 xml 쿼리문의 id명이 같아야 한다.

resultType=" "
: return 타입과 비슷하다고 보면 된다. 경로로 지정된 곳에 값을 넣어준다. (Users users에 값을 넣어준다.)


4. rs와 Java Object 변경 또한 MyBatis 프레임워크가 관리해준다.

profile
코딩을 배우고 기록합니다. 읽는 사람이 이해하기 쉽게 쓰려고 합니다.

0개의 댓글