객체 지향 언어인 자바의 관계형 데이터베이스 프로그래밍을 좀더 쉽게 할 수 있게 도와주는 개발 프레임워크이다. JDBC를 통해 데이터베이스에 엑세스하는 작업을 탭슐화 하고 일반 SQL 쿼리, 저장 프러시저와 고급 캡핑을 지원하면서 JDBC 코드 및 배개 변수의 중복 작업을 제거한다. 프로그램에 있는 SQL쿼리들을 한 구성파일에 구성하여 프로그램 코드와 SQL을 분리할 수 있는 장점이 있다. 분리할 수 있는 장점으로 인해 코드의 간결성, 유지보수성, Vo를 사용하지 않고 사용자 정의 DTO, MAP 등으로 맵핑하여서 사용할 수 있다. 빠른 개발이 가능하며 생산성이 향상된다.
MyBatis는 JDBC와는 다르게 따로 쿼리문을 main/resource에 폴더를 만들어서 mapper에 작성을 한다.
config는 데이터베이스와 프로그램과의 연관을 결정지어주는 곳이다.
mapUnderscoreToCamelCase :데이터베이스의 컬럼이름은 보통 스네이크케이스로 적는다. 이것을 자바에서 사용하는 카멜케이스와 연결 짓기위해서 쓰는 설정이다.
TypeAliases : mapper에서 쿼리문을 작성하려면 parameterType 에 주소를 다적어야 한다. 길게 입력하면 보기도 안좋고 해서 그 주소에 별명을 주는 것이다 .
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.mapper.contact">
<insert id="insert" parameterType="ContactDto">
INSERT INTO CONTACT_T(CONTACT_NO, NAME, TEL, EMAIL, ADDRESS, CREATED_AT) VALUES(CONTACT_SEQ.NEXTVAL, #{name}, #{tel}, #{email}, #{address}, TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'))
</insert>
<update id="update" parameterType="ContactDto">
UPDATE CONTACT_T SET NAME = #{name}, TEL = #{tel}, EMAIL = #{email}, ADDRESS = #{address} WHERE CONTACT_NO = ${contactNo}
</update>
<delete id="delete" parameterType="int">
DELETE FROM CONTACT_T WHERE CONTACT_NO = ${contactNo}
</delete>
<select id="selectList" resultType="ContactDto">
SELECT CONTACT_NO, NAME, TEL, EMAIL, ADDRESS, CREATED_AT FROM CONTACT_T ORDER BY CONTACT_NO ASC
</select>
<select id="selectContactByNo" parameterType="int" resultType="ContactDto">
SELECT CONTACT_NO, NAME, TEL, EMAIL, ADDRESS, CREATED_AT FROM CONTACT_T WHERE CONTACT_NO = ${contactNo}
</select>
</mapper>
mapper : mapper에는 select, delete, update, insert 태그를 사용해서 뭐리눔을 만든다. 태그 속성으로 parameterType, resultType을 줄 수 있으며 각각 전달해주는 타입이나 클래스를 적어주고 결과값이 여러 개가 나오면 DTO나 타입을 적어준다.
@RequiredArgsConstructor
@Repository
public class ContactDao {
private final SqlSessionTemplate sqlSessionTemplate;
/**
* 삽입 메소드<br>
* @param contactDto 삽입할 연락처 정보(name, tel, email, address)
* @return insertCount 삽입된 행(Row)의 개수, 1이면 삽입 성공, 0이면 삽입 실패
*/
public int insert(ContactDto contactDto) {
return sqlSessionTemplate.insert("mybatis.mapper.contact.insert", contactDto);
}
/**
* 수정 메소드<br>
* @param contactDto 수정할 연락처 정보(contact_no, name, tel, email, address)
* @return updateCount 수정된 행(Row)의 개수, 1이면 수정 성공, 0이면 수정 실패
*/
public int update(ContactDto contactDto) {
return sqlSessionTemplate.update("mybatis.mapper.contact.update", contactDto);
}
/**
* 삭제 메소드<br>
* @param contact_no 삭제할 연락처 번호
* @return deleteCount 삭제된 행(Row)의 개수, 1이면 삭제 성공, 0이면 삭제 실패
*/
public int delete(int contactNo) {
return sqlSessionTemplate.delete("mybatis.mapper.contact.delete", contactNo);
}
/**
* 전체 조회 메소드<br>
* @return 조회된 모든 연락처 정보(ContactDto)
*/
public List<ContactDto> selectList() {
return sqlSessionTemplate.selectList("mybatis.mapper.contact.selectList");
}
/**
* 상세 조회 메소드<br>
* @param contact_no 조회할 연락처 번호
* @return contactDto 조회된 연락처 정보, 조회된 연락처가 없으면 null 반환
*/
public ContactDto selectContactByNo(int contactNo) {
return sqlSessionTemplate.selectOne("mybatis.mapper.contact.selectContactByNo", contactNo);
}
}
HiKariCP는 데이터베이스 연결을 관히래 주는 도수(라이브러리)이다.
커넥션(Connetcion Pool)이 설정된 커넥션의 사이즈만큼의 연결을 허용하여 HTTP 요청에 대해 순차적으로 DB 커넥션을 처리해 주는 기능을 수행한다. 가볍고 빠르다는 장점이 있어 사용을 한다.
JDBC 연결은 드라이버를 로드하고 연결하여 객체를 받아와야 하는 과정을 가지고 있다. 이 과정은 매번 사용자가 요청할 때마다 드라이버를 로드하고 커넥션 객체를 생성하여 연결하고 종료하는 과정이 불편하고 속도와 자원소모에 대한 단점이 있었고 이를 보완하기 위하여 데이터베이스 커넥션풀(DBCP)을 사용한다.
@Mapper
public interface ContactMapper {
public int insert(ContactDto contactDto);
public int update(ContactDto contactDto);
public int delete(int contactNo);
public List<ContactDto> selectList();
public ContactDto selectContactByNo(int contactNo);
public int hourlyDelete();
}
인터페이스 파일이며 @Mapper을 붙여서 사용한다.
@Mapper
1. 맵퍼의 쿼리문을 호출할 수 있는 인터페이스에 추가하는 마이바티스 어노테이션
2. 메소드이름과 호출할 쿼리문의 아이디(id)을 동일하게 맞추면 자동으로 호출한다.
3. @mapper가 등록된 인터페이스의 검색이 가능하도록 @MapperScan을 추가해야한다. (sqlSessionTemplate Bean 이 등록된 AppConfig.java에 추가한다. )
4. 매퍼의 namespace 값을 인터페이스 경로로 작성한다.
스프링 배치
사용자와 상호관계 없이 여러개의 작업을 미리 정해진 순서에 따라 중단없이 처리하는 것이다. 시스템의 운영에 있어 대용량 일괄처리의 편의를 위해 설계된 가볍고 포괄적인 배치프레임워크이다. DI, AOP, 서비스 추상화 등 스프링프레임의 3대 요소를 모두 사용할 수 있다 .
스프링배치는 로깅/추적, 트랜잭션 관리, 작업처리 통계, 작업 재시작, 건너뛰기, 리소스 관리등 대용량처리에 필수적인 재사용 가능한 기능을 제공한다.
- 배치를 사용하는 경우
- 대용량의 비지니스 데이터를 복잡한 작업으로 처리해야하는 경우
- 특정한 시점에서 스케쥴러를 통해 자동화된 작업이 필요한 경우
- 대용량 데이터 포맷을 변경 유효성 검사등의 작업을 트랜잭션 안에서 처리후 기록해야하는 경우
스케쥴러
특정한 시간에 등록된 작업을 자동으로 실행시키는 것이다.
1. 추가적인 의존성 불필요
2. 사용이 쉬움
3. 1개의 Tread pool 사용
@Slf4j의 역활 : 여러 로깅 프레임워크의 추상화를 제공해주는 라이브러리이다. 즉 자바에서 쓰이는 다양한 로깅 프레임워크의 API를 제공하는 개념이다. 로깅 시스템을 변경하려고 할 때 코드를 작성할 필요 없이 바인딩을 교체할 수 있다.
@Scheduled(cron= 크론식)
cron 대신 사용할 수 있는 설정
fixedDelay : 작업이 끝난 시점부터 시간을 카운트한다.
fixedRate : 작업이 시작되는 시점부터 시간을 카운트한다.
1. 특정 시간이 특정 서비스를 동작시킬 수 있는 프로그램이다.
2. 크론식으로 동작할 시간을 지정할 수 있다.
3. 크론식
1) 형식
초 분 시 일 월 요일
2) 상세
(1) 초 : 0 ~ 59
(2) 분 : 0 ~ 59
(3) 시 : 0 ~ 23
(4) 일 : 1 ~ 31
(5) 월 : 0 ~ 11 (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC)
(6) 요일 : 1 ~ 7 (MON, TUE, WED, THR, FRI, SAT, SUN)
3) 방식
(1) ? : 설정 없음 ("요일"에서 사용)
(2) * : 매번 ("초 분 시 일 월"에서 사용)
(3) - : 범위
(4) / : 주기
4) 예시
(1) 특정 시간 (금요일 19시 0분 0초에 동작)
0 0 19 * * FRI
(2) 특정 범위 (새벽 1시 0분 0초부터 매분마다 동작)
0 0-30 1 * * ?
(3) 반복 (10초마다 동작)
0/10 * * * * ?
(4) 반복 (10분마다 동작)
0 0/10 * * * ?
(5) 반복 (7시, 19시마다 동작)
0 0 7,19 * * ?
4. 크론식 만들기
https://www.cronmaker.com/
1. 컨트롤러로 들어오는 요청과 응답을 가로챈다.
2. HandlerInterceptor 인터페이스를 구현(권장)하거나, HandlerInterceptorAdapter 클래스를 상속하면 인터셉터가 된다.
3. Spring Container에 Bean으로 등록해 두어야 한다.
4. 주요 메소드
1) preHandle() : 요청 전에 동작할 코드 작성(false를 리턴하면 컨트롤러 요청 동작을 막을 수 있다.)
2) postHandle() : 요청 후에 동작할 코드 작성(컨트롤러의 Handler 동작 이후)
3) afterCompletion() : View까지 처리가 끝난 후 동작할 코드 작성
5. 언제 Interceptor가 동작할 것인지 servlet-context.xml에 작성한다.
1) <mapping> : 인터셉터가 동작할 요청 주소
2) <exclude-mapping> : 인터셉터가 동작하지 않을 요청 주소
3) <beans:bean> : 동작할 인터셉터
6. Filter vs Interceptor
| Filter | Interceptor
------|---------------------------|--------------------------
호출 | DispatcherServlet 실행 전 | DispatcherServlet 실행 후
설정 | web.xml | servlet-context.xml
요청 | 처리함 | 처리함/처리안함