Database/JDBC

JDBC) IntelliJ(Spring Boot) + MySQL 연동 / CRUD TEST

pogun 2025. 3. 20. 00:47

IntelliJ IDEA version : 2024.3.4.1

spring boot version : v3.3.10-SNAPSHOT

MySQL version : 8.0.41

문서를 읽기 전에 전체 디렉토리 구조를 파악하고 읽으면 이해하기 쉬움!

1. 전체 디렉토리 구조

src
├── main
│   ├── java
│   │   └── com.mc.app
│   │       ├── dto                          <- 요기
│   │       ├── frame                        <- 요기  
│   │       ├── repository                   <- 요기
│   │       ├── service                      <- 요기
│   │       ├── controller
│   │       ├── controllerRest
│   │       ├── util
│   │       ├── Day03Application.java
│   │       └── ServletInitializer.java
│   └── resources
│       ├── mapper                           <- 요기
│       ├── static
│       ├── templates
│       ├── application.yml 
│       └── application-dev.yml              <- 요기
└── test
    └── java
        └── com.mc
            ├── cust                         <- 요기
            └── weather

1. MySQL 계정 생성

use mysql;
create database 데이터베이스 이름;
select host, user from user;
create user '이름'@'localhost' identified by '비밀번호';
create user '이름'@'%' identified by '비밀번호';
grant all on mcdb.* to 'mcuser'@'%';
flush privileges;

2. build.gradle에 dependency 추가

// Mybatis & Mysql JDBC Driver
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
runtimeOnly 'com.mysql:mysql-connector-j'

3. properties 설정 (application-dev.yml)

: datasource랑 mybatis 줄 들여쓰기 중요!

: classparh는 기본적으로 resources 파일을 의미

# Spring Config
spring:
  mvc:
    view:
      prefix: /WEB-INF/views/     # 경로
      suffix: .jsp                # 확장자
  datasource:
      url: jdbc:mysql://127.0.0.1:포트번호/DB이름?characterEncoding=utf8
      username: 이름
      password: 비밀번호
      
# Mybatis
mybatis:                                       # classpath 기본 경로는 resources
    type-aliases-package: com.mc.app.dto       # dto 경로 지정
    mapper-locations: classpath:/mapper/*.xml  # mapper 경로 지정

4. resource/mapper 디렉토리에 파일명.xml 생성

: xml파일이 실제 DB 쿼리를 실행하는 파일

parameterType : 보내주는 타입

resultType : 받아오는 타입 (받아올 때 타입을 맞춰서 변환시켜줌)

<?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.mc.app.repository.CustRepository">

    <select id="selectOne" parameterType="String" resultType="cust"> /* com.mc.dto.cust */
        SELECT * FROM cust WHERE id=#{id}
    </select>
    <select id="select" resultType="cust">
        SELECT * FROM cust
    </select>
    <insert id="insert" parameterType="cust">
        INSERT INTO cust VALUES (#{id},#{pwd},#{name})
    </insert>
    <update id="update" parameterType="cust">
        UPDATE cust SET pwd=#{pwd},name=#{name} WHERE id=#{id}
    </update>
    <delete id="delete" parameterType="String">
        DELETE FROM cust WHERE id=#{id}
    </delete>

</mapper>

5. dto/Cust

: 데이터를 담는 객체 (VO / DTO)

: DB의 테이블 구조를 기반으로 생성됨

package com.mc.app.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Cust {
    private String id;
    private String pwd;
    private String name;
}

6. frame : 뼈대를 만들어 놓기(  frame/MCRepository,   frame/MCService )

: frame 패키지는 공통적으로 사용할 추상화된 인터페이스(뼈대) 를 정의하는 곳

: 비즈니스 로직이나 DB 연동을 하다 보면 다양한 도메인(Cust, Board 등)에 대해 CRUD 작업이 반복

: 이 반복되는 메서드의 틀을 미리 인터페이스로 정의해서, 재사용성과 유지보수성을 높이기 위한 설계 방식

MCService.java

package com.mc.app.frame;

import java.util.List;

public interface MCService<V,K> {
    void add(V v) throws Exception;
    void mod(V v) throws Exception;
    void del(K k) throws Exception;
    V get(K k) throws Exception;
    List<V> get() throws Exception;
}

: 서비스 계층의 기본 동작을 정의한 인터페이스

V : 데이터 타입 (예: Cust, Board 등)

K : 키 타입 (예: id - String, 번호 - Integer 등)

MCRepository.java

package com.mc.app.frame;

import java.util.List;

public interface MCRepository<V,K> {
    void insert(V v) throws Exception;
    void update(V v) throws Exception;
    void delete(K k) throws Exception;
    V selectOne(K k) throws Exception;
    List<V> select() throws Exception;
}

: DAO(Data Access Object)의 인터페이스

: DB와 직접 연결되는 로직을 추상화하여, 실제 구현체(repository)가 이 인터페이스를 따르도록 함

7. service/CustService

: CustService는 비즈니스 로직을 처리하는 서비스 계층

: MCService<Cust, String> 인터페이스를 구현하고, 실제 DB 처리는 CustRepository에게 위임한다.

: 즉, Controller → Service → Repository → DB 흐름에서 중간에 위치하며,
: 여기서 검증, 트랜잭션, 데이터 가공 등의 로직을 처리할 수 있다.

package com.mc.app.service;

// 코드가 너무 길어서 import부분은 지움

@Service
@RequiredArgsConstructor
public class CustService implements MCService<Cust, String> {

    final CustRepository custRepository;

    @Override
    public void add(Cust cust) throws Exception {
        custRepository.insert(cust);
    }
    @Override
    public void mod(Cust cust) throws Exception {
        custRepository.update(cust);
    }
    @Override
    public void del(String s) throws Exception {
        custRepository.delete(s);
    }
    @Override
    public Cust get(String s) throws Exception {
        return custRepository.selectOne(s);
    }
    @Override
    public List<Cust> get() throws Exception {
        return custRepository.select();
    }
}

8. repository/CustRepository

: CustRepository는 DB와 실제 연결되어 SQL을 실행하는 DAO(Data Access Object) 이다.

: MyBatis의 Mapper XML 파일(custmapper.xml)과 연결되어 있고, @Mapper로 마이바티스가 해당 인터페이스의 구현체를 자동 생성

package com.mc.app.repository;

import com.mc.app.dto.Cust;
import com.mc.app.frame.MCRepository;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface CustRepository extends MCRepository<Cust, String> {}

: 인터페이스만 정의하면, MyBatis가 mapper XML을 통해 자동으로 구현체를 생성

: CustRepository는 MCRepository를 상속하므로 기본 CRUD 메서드를 갖는다.

: 실질적으로는 custmapper.xml에 정의된 SQL이 실행

<cust, String> : String 부분은 무조건 래퍼클래스를 사용해야 한다.

: DTO 부분에 idint여도 여기선 Integer를 사용해야 한다.

9. 흐름 요약 ( Controller → DB까지 )

요청 → Controller
     → Service (비즈니스 로직)
     → Repository (DAO: DB에 접근)
     → Mapper XML (SQL 실행)
     → DB
     → 결과를 다시 Controller로 반환
계층 설명
DTO 데이터를 담는 객체
Frame 공통 인터페이스 정의
Service 비즈니스 로직 처리
Repository DB 접근
Mapper XML 실제 SQL 실행
Controller 요청/응답 처리

10. test/java/com/mc/cust (CRUD)

: Insert, Update, Select, SelectOne, Delete test

Insert

@SpringBootTest
@Slf4j
class InsertTest {

    @Autowired
    CustService custService;
    
    @Test
    void contextLoads() {
        Cust cust = Cust.builder().id("id10").pwd("pwd10").name("구름이").build();

        try {
            custService.add(cust);
            log.info("OK!!");
        } catch (Exception e) {
            log.info("id 중복!!");
        }
    }
}

Update

@SpringBootTest
@Slf4j
class Update {

    @Autowired
    CustService custService;

    @Test
    void contextLoads() {
        Cust cust = Cust.builder().id("id02").pwd("222222").name("김튜브").build();

        try {
            custService.mod(cust);
            log.info("OK!!");
        } catch (Exception e) {
            log.info("id 중복!!");
        }
    }
}

Select, SelectOne

@SpringBootTest
@Slf4j
class Select {

    @Autowired
    CustService custService;

    @Test
    void contextLoads() {
        List<Cust> custs = null;
        try {
            custs = custService.get();
            log.info("OK:"+custs);
        } catch (Exception e) {
            log.info("Id 중복");
        }
    }
    
    @Test
    void contextLoads2() {
        Cust cust = null;
        try {
            cust = custService.get("id01");
            log.info("OK:"+cust.toString());
        } catch (Exception e) {
            log.info("Id 중복");
        }
    }
}

delete

@SpringBootTest
@Slf4j
class Update {

    @Autowired
    CustService custService;

    @Test
    void contextLoads() {
        Cust cust = Cust.builder().id("id02").pwd("222222").name("김튜브").build();

        try {
            custService.mod(cust);
            log.info("OK!!");
        } catch (Exception e) {
            log.info("id 중복!!");
        }
    }
}

'Database > JDBC' 카테고리의 다른 글

JDBC) eclipse + MySQL 연동  (0) 2025.02.11