분류

2021년 5월 24일 월요일

spring boot기반 batch 프로젝트 생성부터 mybatis 연동 단순하게.

 개요 

회사에서 배치 프로세스를 분리해야 하는 일이 생겼습니다. 인터넷으로 이런 저런 조사를 해보는데 정상적인 문서를 찾기 힘든 것이 현실이고, 구했다 하더라도 입맛에 맞는 구조가 아닌 경우가 많아 최소한의 soruce를 통해 mybatis 연동(MariaDB)까지 정리 해보려 합니다. 

본문의 순서는 다음과 같이 진행 하겠습니다.

1. Eclipse spring Boot 설치 

2. Project 생성 

3. Project 환경 설정 

4. application.properties 설정 

5. Source 코드 생성 

6. 발생할 수 있는 오류

순으로 정리되어있습니다. 캡처를 할 경우 너무 여러 장을 찍어야 하기에 설치 순서는 동영상으로 대체하였습니다. 

그럼 시작하겠습니다. 


1. Eclipse spring Boot 설치 

일단 spring boot 프로젝트를 생성하기 위해서는 Eclipse의 Spring Tool이 필요합니다. Eclipse의 Help 버튼을 눌러 Market Place에 들어가서  Spring Tool을 검색해서 Install 하고 Eclipse를 다시 시작 합니다. 

Spring Tool 인스톨 영상 

2. Project 생성 

Project의 생성은 create a new project -> spring 검색 -> Spring Starter Project -> java 버전 선택 -> project 및 package 명 변경 -> spring batch 선택 -> Mybatis Framework 선택 -> finish 순으로 진행하였습니다. 

project 생성 영상 


3. Project 환경 설정


환경설정에 연관된 파일
환경설정에 연관된 파일은 2가지입니다. 
1) pom.xml을 통한 라이브러리 환경 설정과 
2) 프로젝트 환경 설정의 application.properties 파일입니다. 

1) 라이브러리 환경설정 

우선 저는 mariadb를 연결해야 하기에 mariadb의 maven 라이브러리를 pom.xml에 추가하겠습니다. maven을 통한 라이브러리 추가는 google 에서 maven +라이브러리 를 검색하거나 
메이븐 사이트 https://mvnrepository.com/

위 링크로 접속하셔서 해당 라이브러리를 검색하시면 쉽게 dependency 정보를 찾을 수 있습니다. 

mysql 드라이버 정보


검색된 메이븐 라이브러리중 자신에게 해당하는 버전을 클릭하면 이렇게 하단에 디팬던시 정보가 표기되어 해당 정보를 pom.xml에 붙여넣기 하면 됩니다.

pom.xml에 붙여넣기



4. application.properties 설정 

application.properties에 프로젝트에 사용할 환경 설정을 추가해줍니다. application.properties 는 spring toole에서 자동 완성을 지원합니다. 구동 화면은 아래와 같습니다. 
application.property 설정 영상

실제 application.properties에 수록된 내용은 다음과 같습니다. 
#데이터 베이스 연결에 사용할 드라이버 
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#데이터베이스 url 
spring.datasource.url=jdbc:mysql://192.168.0.1:6330/test?serverTimezone=UTC&characterEncoding=UTF-8
#계정 
spring.datasource.username=testUser
#비밀번호
spring.datasource.password=testUser

#mapper 파일이 적재될 위치 sql mapper 파일과 동일하게 맞춰준다.
mybatis.mapper-locations=com/springBatchTest/mapper/*.xml
#커스텀 환경변수 
custom.test=test-value


5. Source 코드 생성 

우선 application.properties에 설정한 위치에 mapper xml파일을 만들어줍니다. 
환경설정 순서(클릭시 커짐)
현재 프로젝트의 application 설정이 마이바티스 까지 연동되는 구조는 다음 순서에 따라 이루어집니다. 
application에서 모델을 연결해주는 것은 mapper location.
모델과 컨트롤러의 연결은 xml 파일내의 namespace가 classPath로 역할을 하게 되더군요. 

수정 및 생성한 소스프로그램은 총 4개의 파일입니다. 
1) testMapper.xml 
2) TestDataMapper.java
3) TestDataService.java
4) SpringBatchTestApplication.java
차례대로 기술하겠습니다. 

1) testMapper.xml 

mysql DB에서 데이터를 조회할 sql 문을 입력합니다. 또한 namespace에 java에서 연동할 인터페이스의 패키지 경로와 파일명을 입력합니다. 
<?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="com.springBatchTest.mapper.TestDataMapper">

<!-- 수행할 sql -->
    <select id="getTestDataList" resultType="java.util.Map">
<![CDATA[
SELECT 1 AS COL1 
UNION ALL 
SELECT 2 AS COL1
]]>
    </select>
</mapper>
sql은 간단하게 테스트를 수행할 수 있게 정의하였습니다. 

2) TestDataMapper.java

mapper.xml 에 정의된 위치에 정의된 명칭으로 생성해줍니다. 인터페이스 내부에는 xml에 정의된 sql과 동일한 명칭 그리고 동일한 데이터 형식을 갖고 있는 함수가 있어야 합니다. 
package com.springBatchTest.mapper;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface TestDataMapper {
List<Map<String, Object>> getTestDataList();
}
mybatis framework과 java Application간의 인터페이스 역할만 해주므로 정말 내용이 없습니다. SQL이 늘어나는 만큼 증가합니다. 

3) TestDataService.java

서비스에는 인터페이스에 정의된 형식과 동일한 서비스를 구성해줍니다. 이 파일 역시 자동 연결을 위한 선언 ,  서비스 선언 이외에 특별한 내용이 없습니다. 
package com.springBatchTest.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;

import com.springBatchTest.mapper.TestDataMapper;

@Service
public class TestDataService {
    @Autowired
    TestDataMapper testData

    public List<Map<String, Object>> getTestDataList() {
        return testData.getTestDataList(); 
    }
}


4) SpringBatchTestApplication.java

package  com.springBatchTest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.List;
import  java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import  com.springBatchTest.service.TestDataService;

@SpringBootApplication
public class SpringBatchTestApplication {
public static void main(String[] args) {
try (ConfigurableApplicationContext ctx = SpringApplication.run(SpringBatchTestApplication.class , args)) {
SpringBatchTestApplication m = ctx.getBean(SpringBatchTestApplication.class );
m.selectDataf(); 
}catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
}
  @Autowired
  TestDataService  testDataService;
    public void selectDataf() {
    List<Map<String, Object>> tmp = testDataService.getTestDataList();
    System.out.println(tmp.size());
    }
}


자 이제 테스트용 코드 생성은 끝났습니다. 

6. 발생할 수 있는 오류

1) 정상 처리 시 디버깅 콘솔 내용 


2021-05-24 19:28:03.528  INFO 10964 --- [           main] c.s.SpringBatchTestApplication           : Starting SpringBatchTestApplication using Java 15.0.1 on DESKTOP-3QN7REN with PID 10964 (D:\blogger\springBatchTest\target\classes started by jinyboys in D:\blogger\springBatchTest)
2021-05-24 19:28:03.533  INFO 10964 --- [           main] c.s.SpringBatchTestApplication           : No active profile set, falling back to default profiles: default
2021-05-24 19:28:06.259  INFO 10964 --- [           main] c.s.SpringBatchTestApplication           : Started SpringBatchTestApplication in 3.553 seconds (JVM running for 4.553)
2021-05-24 19:28:06.277  INFO 10964 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...

2021-05-24 19:28:06.771  INFO 10964 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2
2021-05-24 19:28:06.897  INFO 10964 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
945  INFO 10964 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

수행할 로직이 없기 때문에 약 3,4초만에 수행되고 종료되며 임시로 생성된 sql에서 받는 데이터 2건에 대한 사이즈 정보가 표기됩니다. 

2) application.properties내의 mapper 경로가 잘못 된 경우  

빨간색 글자처럼 파일을 찾을 수 없다는 메시지가 나옵니다. 
2021-05-24 19:31:39.543  INFO 7172 --- [           main] c.s.SpringBatchTestApplication           : Starting SpringBatchTestApplication using Java 15.0.1 on DESKTOP-3QN7REN with PID 7172 (D:\blogger\springBatchTest\target\classes started by jinyboys in D:\blogger\springBatchTest)
2021-05-24 19:31:39.553  INFO 7172 --- [           main] c.s.SpringBatchTestApplication           : No active profile set, falling back to default profiles: default
2021-05-24 19:31:42.462  INFO 7172 --- [           main] c.s.SpringBatchTestApplication           : Started SpringBatchTestApplication in 3.802 seconds (JVM running for 5.327)
2021-05-24 19:31:42.479  INFO 7172 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...

2021-05-24 19:31:42.987  INFO 7172 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2021-05-24 19:31:43.074  INFO 7172 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2021-05-24 19:31:43.086  INFO 7172 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
Invalid bound statement (not found): com.springBatchTest.mapper.TestDataMapper.getTestDataList

3) mapper.xml 파일 내부 SQL구문의 ID와 mapper.java 인터페이스가 불일치 할 경우

위와 동일한 오류가 발생합니다. 
 Invalid bound statement (not found): com.springBatchTest.mapper.TestDataMapper.getTestDataList

4) service.java 클래스 내에 @Autowired 설정이 없는 경우

Cannot invoke "com.springBatchTest.mapper.TestDataMapper.getTestDataList()" because "this.testData" is null

5) mapper.java 클래스가 없거나 비정상 , @mapper 설정이  없는 경우

Description:

Field testData in com.springBatchTest.service.TestDataService required a bean of type 'com.springBatchTest.mapper.TestDataMapper' that could not be found.

The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.springBatchTest.mapper.TestDataMapper' in your configuration.

Error creating bean with name 'springBatchTestApplication': Unsatisfied dependency expressed through field 'testService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testDataService': Unsatisfied dependency expressed through field 'testData'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.springBatchTest.mapper.TestDataMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}


이상 스프링 배치 프로젝트 생성부터 mybatis 연동까지 그리고  발생할 수 있는 오류까지 알아봤습니다. 

이렇게 쉽게 4개의 파일만 설정하면 연동할 수 있는 기본적인 형태를 이해하지 못하고 엉뚱하게 정리 해 놓은 글들이 너무 많아 직접 정리를 해 보았습니다. 누군가에게 도움이 되면 좋겠네요 ㅎㅎ. 

2021년 5월 23일 일요일

자전거 코스 대전 -> 청주 무심천

개요 

지난번에 약 80km의 거리 주행 이후 이번주에는 100km를 넘겨보겠다는 생각에 대전에서 청주의 무심천을 잇는 약 110km 주행 코스를 만들어보았습니다. 참고로 청주의 무심천은 봄철에 벚꽃이 이쁘게 피어 사람들이 많이 다니는 곳 입니다. 

코스 난이도 기난이도 기준은 3가지이며 다음과 같습니다. 

1. 거리 20km 마다 1점 

2. 업힐 200m 마다 1점 

3. 보급 20km 마다 확보되지 않을 경우 보급 주의를 표시하도록 하겠습니다. 보급은 편의점을 기준입니다. 보급 상태가 주의 일 경우 50km 당 음료수 1리터, 에너지바 1개는 있어야 달릴 만 합니다. 

점수가 높을수록 난이도가 어렵다고 생각 하시면 됩니다. 평균은 거리와 업힐의 평균입니다. 

평균 점수 기준  1~3점 초급, 4~6점 중급 7~9점 고급  10점 이상 특급 되겠습니다.

현 코스의 난이도는 다음과 같습니다. 

1. 거리 :  6

2. 업힐 :  3

3. 보급 : 주의 

평균 : 4.5점 중급


1. 코스파일 

대전 -> 청주 무심천.tcx

대전 -> 청주 무심천.gpx

코스 파일은 두 가지 중 본인에게 맞는 파일을 선택해서 다운로드 받으시면 됩니다.


2. 코스 개요 

대전에서 강변을 따라 청주를 일주하는  코스이며 중간에 약 5km 가량의 국도가 포함되어있습니다. 보급포인트는 약 40km 언저리에서 편의점과 짬뽕집(개인적인 욕심), 식당가 등을 표기하여 놓았습니다. 

코스의 특징은 경유 4에 해당하는 대청댐을 통과 할 때 약 12%의 경사가 있고 해당 지역에 고도가 몰려 있습니다. 따라서 후반 체력이 딸린다면 우측으로 1회전 후반 체력에 문제가 없다면 좌측으로 1회전을 도시면 되겠습니다. 

대전 - 청주 무심천 1회전 코스

해당 구간 레포트
획득고도는 643m 로 대전 -> 세종 호수공원 코스에 비해 약 250m 밖에 높지 않으나 무심천 -> 대청댐 구간이 약한 오르막이 지속되는 형태입니다. 
초반에 강오르막 하나 지나고 쭉 편하게 가느냐. 후반을 힘들게 달리느냐는 개인 취향에 맡기겠습니다. 


3. 코스 주행 후기 

해당 코스 주행기록 
시작 위치를 약간 조정하는 바람에 gpx 리포트보다 20km 짧게 다녀왔습니다. 매도 먼저 맞는 편이 좋을 것 같아 대청댐 방향으로 출발했습니다. 원래 코스보다 짧아졌지만 업힐의 변화는 없기에 실제 오르막은 427이 맞을 것 같습니다. 

100km 가까운 주행인데 저녁 약속이 있어 중간 보급지점을 모두 건너뛰었더니 후반부에 칼로리 부족으로 힘이 딸립니다. 에너지바 2개정도는 보급품으로 챙겨가는 것이 어떤가 합니다. 실수로 포도당 캔디도 안 챙기는 바람에 더욱 힘들었습니다. 

또한 여름에 가까운 기온 때문에 땀을 많이 흘려 물도 1리터로는 부족했습니다. 

주의사항 
1. 지도상으로 12시 방향 정도 되는 부근에 공사현장이 있습니다. 청주와 세종의 중간 점. 길이 좁아지고 코너가 안보이니 속도를 줄이세요. 오늘 길막 당해서 사고났습니다. 블랙박스 안달고 갔는데 길막 한 분이 넘어지는 걸 보시고 튀더라구요. 보험 가입해야겠습니다. ; 

2. 2회 주행 결과 해당 길에 노인분들이 MTB로 많이 다니시는데 오르막에서 와리가리를 심하게 합니다. 내리막 추돌 주의하셔야 합니다. 

2. 청주방면은 화장실과 휴식공간이 별로 없고, 청주와 세종 사이에 보급을 할 수 있는 포인트가 약 1시간 가량 찾을 수 없습니다.  무엇보다 물 확보를 꼭 하셔야 합니다. 그리고 2회 다녀온결과 청주엔 화장실이 없습니다. (있긴 한데 없다고 할만큼 적습니다. ) 

대청댐 현암정 전경

대청댐 현암정 전경

청주 무심천



2021년 5월 9일 일요일

자전거 코스 대전 -> 세종호수공원

 개요 

어김없이 봄은 왔고, 자전거 타기 좋은 날씨가 계속 되고 있습니다. 오랜만의 외출이기도 해서 큰 무리 없이 다녀올 수 있는 80km 의 코스를 만들어보았습니다. 획득 고도는 약 450m로 거리에 비해 업힐이 적은 편이며, 중간에 보급 포인트로 편의점과 식당의 위치를 찍어 놓았습니다. 

코스 난이도 기준을 잡아보았습니다. 난이도 기준은 3가지이며 다음과 같습니다. 

1. 거리 20km 마다 1점 

2. 업힐 200m 마다 1점 

3. 보급 20km 마다 확보되지 않을 경우 보급 주의를 표시하도록 하겠습니다. 보급은 편의점을 기준입니다. 보급 상태가 주의 일 경우 50km 당 음료수 1리터, 에너지바 1개는 있어야 달릴 만 합니다. 

점수가 높을수록 난이도가 어렵다고 생각 하시면 됩니다. 평균은 거리와 업힐의 평균입니다. 

평균 점수 기준  1~3점 초급, 4~6점 중급 7~9점 고급  10점 이상 특급 되겠습니다.

현 코스의 난이도는 다음과 같습니다. 

1. 거리 :  4

2. 업힐 :  2

3. 보급 : 주의 

평균 : 3점 초급


1. 코스파일

대전 -> 세종호수공원 tcx

대전 -> 세종 호수공원 gpx

코스 파일은 두 가지 중 본인에게 맞는 파일을 선택해서 다운로드 받으시면 됩니다. 

2. 코스 개요 

엑스포에서 대청댐을 가는 방면에 있는 원촌교에서 시작합니다. 원촌교는 벚꽃이 약 2km 가량 이어지는 벚꽃 시즌에 꼭 가볼만한 장소기도 하구요 주변에 주차할 수 있는 공간이 제법 있는 편입니다. 그래서 종종 활용합니다. 

1) 원촌교 

2) 보급 

3) 세종 호수 공원 서측 출입구

4) 세종 호수 공원 북측 출입구 

5) 보급 

6) 원촌교

의 코스입니다.

길은 100% 자전거길로 갈수도 있고, 천변은 자전거길과 국도가 같이 있어 선택해서 달릴 수 있습니다. 코스 자체는 자전거 전용도로로 구성되어있습니다. 

코스 레포트
대부분 평지로 이루어져 있고 대부분 4% 경사각이 낮은 업힐입니다. 또한 업힐이 길게 이어지지 않기 때문에 별로 힘들지 않고 다녀올 수 있습니다. 


3. 주행 후기 

평소 자주 다니던 길 이기에 별 무리 없이 다녀왔지만, 그간 체력 훈련을 게을리 한 상태여서 다녀오고 나니 조금 아프긴 합니다. 자전거 도로 좌우로 쉴 곳이 자주 있어 체력이 약한 분들도 어렵지 않게 왕복 할 수 있을 거라 보입니다. 

왕복 85km 업힐은 378m 왕복 이후 엑스포 남문 광장을 조금 돌아 100km를 채웠습니다. gps는 가끔 보며 자전거 길만 따라가면 끝이라 딱히 안내할게 없습니다. 길 찾기 난이도 슈퍼 이지 입니다. 


1) 보급 진입로 
세종시에 거의 도착할 때 쯤 합강공원 언저리에 2개의 보급 포인트가 있습니다. 하나는 GS 편의점이고 다른 하나는 식당과 까페가 모여있는 곳입니다. 참고로 까페에서는 음료 외에 볶음밥 같은 몇 가지 요리를 판매합니다. 다만 일 하시는 분이 주문을 잘 못 알아듣습니다.
그래도 밥 달라면 밥 주고 빵 달라면 빵 주니 대충 먹으면 됩니다. 빵 달라는 데 국 주는 정도는 아닙니다.

편의점은 자전거 도로와는 50m 가량 떨어져있어 지도를 보고 찾아가셔야 합니다. 

식당은 아래 나온 동영상 대로 진입로 입간판이 세워져있어 보고 들어가시면 됩니다. 다만 너무 늦은시간에는 영업하지 않는 것 같습니다. 따라서 야간 라이딩시에는 편의점을 이용하시면 되겠습니다. 

대전 -> 세종 호수공원 풀코스 파일입니다. 2배속 할걸 그랬네요 ㅎㅎ;;;



이상 안전하고 즐거운 자전거 여행 되시길 기원합니다.