본문 바로가기
Spring

[Spring boot] Mybatis Tibero 연동

by amoomar 2023. 3. 27.
반응형

 

VO고 뭐고 나발이고 아무것도 없이 그저 생성 옵션을 gradle, war로 설정한 Spring boot프로젝트에 Tibero로 Mybatis연동 과정만을 정리한 게시글이다. 목차는 아래와 같다.

01. 구조 만들기 : 폴더 생성

02. 구조 채우기
   01) build.gradle 편집
   02) application.properties 편집
   03) SqlSessionFactory
   04) mapper
   05) service
   06) controller

03. 연동 확인

 


 

01. 구조 만들기 : 폴더 생성

작업을 진행하기에 앞서, 추가로 생성된 파일을 적재할 구조들을 생성해줄 필요가 있다. 본인의 경우 아래 사진과 같이 하였다.

예시

 

 


 

02. 구조 채우기

작업은 흐름대로만 설명하자면, mybatis기본 설정을 파일에 정리하고, 각 역할을 담당한 파일들도 내용을 정의하여준 후에 작업한 파일들을 연결해주는 방식으로 진행된다.

 

 

01) build.gradle 편집

JDBC와 Mybatis를 활용하기 위해서는 각 라이브러리들을 프로젝트에 추가해주는 작업이 필요하다.

 

티베로의 경우에는 라이브러리가 코드 형태로는 참조되지 않아, 로컬에 설치되어있는 라이브러리를 직접 프로젝트에 참조해주어야 한다.

 

보통 Tibero를 설치하면 해당 디렉토리 안에 첨부된 라이브러리를 잘 찾아보면 tibero jdbc어쩌구 jar파일이 존재한다고 한다. 그 라이브러리를 프로젝트에 추가한다고 생각하면 되는데, 검색을 해보니 어떤 블로그에서는 tibero6-jdbc.jar라고 하고 또 어떤 블로그에서는tibero6-jdbc-14.jar라고 하더라. 설치 당시 사용자의 JDK버전에 따라 상이한 라이브러리가 설치되는 것으로 보인다. 그냥 둘 중 본인이 가지고 있는 아무 라이브러리를 사용하면 된다.

 

두 라이브러리 차이에 대해 좀 더 구체적인 내용을 확인하고 싶다면 아래 링크를 참고할 수 있겠다.

https://amagrammer91.tistory.com/132

 

[Tibero] tibero6-jdbc.jar 와 tibero6-jdbc-14.jar 차이점

Tibero에서는 Java 프로그램 안에서 SQL 문장을 실행하기 위해 데이터베이스를 연결해주는 애플리케이션 프로그램의 인터페이스를 제공한다. 이러한 인터페이스를 tbJDBC(Tibero의 Java Database Connectivity

amagrammer91.tistory.com

 

위에서 언급한 jar파일을 알맞은 위치에 배치해주고 

 

 

 

build.gradle파일의 dependencies 단락 안에 tibero라이브러리를 implementation해주면 된다. 하는김에 마이바티스도 같이 해주면 일단 의존성 주입은 끝이다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.4' //마이바티스
    implementation files('libs/tibero6-jdbc.jar') //티베로
}

 

 


 

02) application.properties 편집

resources폴더 안에 존재하는 해당 파일에 tibero에 접속하기 위한 Data Source정보를 정의하여주고, 추가로 mapper.xml파일이 참조가 가능하도록 경로 정보도 함께 기입해주어야한다.

#tibero setting
spring.datasource.url=jdbc:tibero:thin:@IP:포트번호:DB이름
spring.datasource.username=DB유저이름
spring.datasource.password=비번
spring.datasource.driver-class-name=com.tmax.tibero.jdbc.TbDriver

#mybatis setting
mybatis.mapper-locations=classpath:mappers/*.xml

 

 

내껀 여깄지 ~~


 

 

03) SqlSessionFactory

SqlSessionFactory를 생성해주는 작업을 진행하도록 한다. 해당 객체는 실질적으로 Mybatis와 DataSource(DB정보)를 참조하여 연결해주고, SQL을 실행할 수 있도록 하는 역할을 한다. 이 객체를 생성해주기 위해 config따위의 키워드를 붙여 별도 class파일을 생성해주기도 하나, 본인의 경우 프로젝트 생성시 기본적으로 만들어진 Application.java파일에 객체 생성 로직을 추가해주는 방식으로 진행하였다. 내용은 아래와 같다.

 

package com.ham.backend;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

@SpringBootApplication
@MapperScan("com.ham.backend.mapper") //mapper.java파일들이 존재하는 디렉토리
public class BackendApplication {

    public static void main(String[] args) {
        SpringApplication.run(BackendApplication.class, args);
    }

    @Bean //이 메서드를 객체생성해줘야 한다.
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {

        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource); //의존성 주입 -servlet-context에서 해주는 작업

        Resource[] res = new PathMatchingResourcePatternResolver()
                .getResources("classpath:mappers/*.xml");//*를써서 여러개xml을 받아서 배열씀

        sessionFactory.setMapperLocations(res);

        return sessionFactory.getObject();
        //.xml 형태의 모든 파일을 받기때문에 배열로 받는다.
        //만약 한가지만 받으면 배열로[] 받을 필요가 없다.
    }

}

 

 


 

04) mapper

mapper파일은 Interface를 정의한 class파일과 SQL문, 그 외 정보를 담은 xml파일로 구분된다.

 

① .java

package com.ham.backend.mapper;

import com.ham.backend.vo.YeboVO;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface YeboMapper {

    public List<YeboVO> getYeboList() throws Exception;

}

 

본인의 경우 SqlSessionFactory객체가 insert, selectOne등 지원메소드만 사용할 것이 아니라 mapper.xml에서 id로 직접 명시한 내용으로 호출할 목적으로 @Mapper를 활용하여 작업하였다. 이 언급에 대한 더 자세한 내용을 확인하고 싶다면 아래 블로그 게시글을 확인할 수 있다.

https://twofootdog.github.io/Spring-DAO%EC%99%80-Mapper%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90/

 

[Spring]DAO와 Mapper의 차이점 | 두발로걷는개

두발로걷는개의 Blog

twofootdog.github.io

 


 

② .xml

본인의 경우 application.properties파일에서 alias를 별도로 정의해주지 않았기 때문에, vo를 참조하기 위해서 모든 nameSpace를 적어주어야한다.

<?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.ham.backend.mapper.YeboMapper">

    <select id="getYeboList" resultType="com.ham.backend.vo.YeboVO">
        SELECT RK, YEBODATE, SCHEDULE, INSDATE, AGGR_CONCAT(YEBO1, '||') AS YEBO1, MAX(YEBO2) AS YEBO2 FROM BIGWEB3.WEATHER_DATA GROUP BY RK, YEBODATE, SCHEDULE, INSDATE
    </select>
    
</mapper>

 

참고로 vo객체를 활용하여 데이터를 관리한다면, 다른 자료형(List, HashMap....)을 활용하게 되더라도 최종 제네릭이 vo라면 result혹은 parameter타입 또한 그 최종 제네릭인 vo를 참조하도록 하여야 오류가 발생하지 않는다.

 

 


 

05) service

 

① Interface

service파일이 필수적으로 가져야하는 메서드를 정의하여 service의 기본 틀을 만들 목적으로 Interface파일을 작성한다.

package com.ham.backend.service;

import com.ham.backend.vo.YeboVO;
import java.util.List;

public interface YeboService {

    public List<YeboVO> getYeboList() throws Exception;
    
}

 

 


 

 

② Class

위에서 규정된 내용을 활용하여 실직적인 기타 행위들을 정의할 목적으로 class파일을 생성함과 동시에 implement도 진행한다.

package com.ham.backend.service.impl;

import com.ham.backend.mapper.YeboMapper;
import com.ham.backend.service.YeboService;
import com.ham.backend.vo.YeboVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("yeboService")
public class YeboServiceImpl implements YeboService {

    @Resource
    private YeboMapper yeboMapper;

    @Override
    public List<YeboVO> getYeboList() throws Exception {
        List<YeboVO> yeboList= yeboMapper.getYeboList();
        return yeboList;
    }
}

 

 


 

06) controller

package com.ham.backend.controller;

import com.ham.backend.service.YeboService;
import com.ham.backend.vo.YeboVO;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController //@ResponsBody생략 가능, 그래도 Json으로 반환됨
public class ApiController {

    //멤버변수
    @Resource(name = "yeboService")
    private YeboService yeboService;

    // 요청처리 로직
    @GetMapping("/ask")
    public List<YeboVO> ask() throws Exception {
        List<YeboVO> yeboList=yeboService.getAsk();
        return yeboList;
    }

}

 

 

 

요청에 대한 결과를 json형식으로 반환하기 위해 @RestController를 활용하였는데, 이때 JsonObject의 key값을 VO와 매핑하기 위해 VO에도 필요 내용을 추가할 필요가 있다.

package com.ham.backend.vo;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class YeboVO {

    // 멤버변수
    private String rk;
    private String yeboDate;
    private String schedule;
    private String insDate;
    //.
    //.
    //(생략)

    // 게터세터
    public String getRk() {
        return rk;
    }

    public void setRk(String rk) {
        this.rk = rk;
    }
    //.
    //.
    //(생략)
    
    //투스트링
    @Override
    public String toString() {
        return "{" +
                "rk:'" + rk + '\'' +
                ", yeboDate:" + yeboDate +
                ", schedule:'" + schedule + '\'' +
                ", insDate:" + insDate +
                ", yebo1:'" + yebo1 + '\'' +
                ", yebo2:'" + yebo2 + '\'' +
                ", weather1:'" + weather1 + '\'' +
                ", wether2:'" + wether2 + '\'' +
                ", status1:'" + status1 + '\'' +
                ", status2:'" + status2 + '\'' +
                ", temp1:'" + temp1 + '\'' +
                ", temp2:'" + temp2 + '\'' +
                ", prcp1:'" + prcp1 + '\'' +
                ", prcp2:'" + prcp2 + '\'' +
                ", etcpr1:'" + etcpr1 + '\'' +
                ", etcpr2:'" + etcpr2 + '\'' +
                ", exist:'" + exist + '\'' +
                '}';
    }
}

 

 

아래에 참조된 링크들을 통해 간략한 설명으로 부족한 내용을 확인해볼 수 있다.

https://cbw1030.tistory.com/315

 

[스프링부트] @JsonNaming, @JsonProperty는 언제 사용할까?

@JsonNaming, @JsonProperty의 사용법을 소개하기에 앞서 사용할 코드를 작성하도록 하자. json으로 넘어오는 값이 아래와 같다고 가정하자(post든 put이든 ..) { "my_name": "kevin", "my_age": 20, "my_country": "korea" }

cbw1030.tistory.com

https://mangkyu.tistory.com/49

 

[Spring] @Controller와 @RestController 차이

Spring에서 컨트롤러를 지정해주기 위한 어노테이션은 @Controller와 @RestController가 있습니다. 전통적인 Spring MVC의 컨트롤러인 @Controller와 Restuful 웹서비스의 컨트롤러인 @RestController의 주요한 차이점

mangkyu.tistory.com

https://code-lab1.tistory.com/259

 

[Spring] @RequestMapping, @GetMapping, @PostMapping에 대하여

@RequestMapping 실무에서 사용되는 대부분의 컨트롤러는 @RequestMapping을 사용한다. 컨트롤러의 메서드에 @RequestMapping 어노테이션을 붙이면 해당 URL이 호출될 때 이 메서드가 호출된다. 어노테이션을

code-lab1.tistory.com

 

 


 

03. 연동 확인

정상적인 실행 결과를 확인할 수 있다.

이하 생략

 


 

반응형