안녕하세요 코골면서 딩가딩가입니다. 😃😃😃  이번에는 Springboot - Mybatis 실습을 해보려고 합니다. 이번실습도 SQL을 실행하여 작업하기 때문에 JDBC Temlpate 공부는 필수입니다. 잘 모르시는분들은 이전 글 참고해주세요!

06. Spring - ★JDBCTemplate 연동★

+ 실습에 들어가기전에 ( ※ 이번실습은 매우매우 중요해서 정말 열심히 공부해보겠습니다. ※) (★★★★★★★★★★★ 중요 ★★★★★★★★★★★) 들어가기에 앞서, 이번 실습은 준비물

mom11230.tistory.com

그럼시작해보겠습니다!!! (●'◡'●)

 
 
 
 
✅ 00. MyBatis 흐름
이전 JDBC Template을 통해 SQL을 실행하였다면 MyBatis는 해당 흐름을 전용 라이브러리를 통해 대체하여 동작합니다.
 

 
 
✅ 01. MyBatis 동작 구조

MyBatis동작 구조입니다. 위에 그림에서 나온 DAO-Mybatis설정 파일에 대한 자세한 설명입니다. 보시고 참고하시면 좋을 것 같아요!
 
 
 
✅ 02. MyBatis 내장 별칭

 
MyBatis에서 사용되는 타입입니다. java랑 다른 타입을 사용하고 있으니 숙지하셔야 합니다.
 
 
 
✅ 03. mapper.xml 작성
가. 작성예시
MyBatis에서 mapper.xml 파일은 SQL 쿼리와 Java 메서드 간의 매핑을 정의하는 역할을 합니다. 이 파일은 SQL 매핑을 위한 XML 파일이며, MyBatis는 이를 사용하여 데이터베이스와 상호 작용합니다.
mapper.xml 파일에는 다음과 같은 내용이 포함될 수 있습니다:
 
  1. SQL 쿼리: 데이터베이스에서 실행할 SQL 쿼리를 포함합니다.
  2. 매개변수 매핑: SQL 쿼리의 매개변수를 Java 객체에 매핑하는 규칙을 정의합니다.
  3. 결과 매핑: SQL 쿼리의 결과를 Java 객체에 매핑하는 규칙을 정의합니다.

 
이번 실습에서 .xml을 수정해 mybatis 를 사용할 수 있게 해주는 mapper.xml 작성 요령입니다. 실습을 하면서 다시 활용해보겠습니다.
 
 
 
 

한국어 개발환경좀 만들어주세요...영어너무많아..

 
 
 
 
나. 작성요령

 
 
mapper.xml 작성요령입니다. INSERT, UPDATE, DELETE 태그는 같은 설정값을 가지니 참고합시다!
 
 
✅ 04. <select>태그 주요 속성

 
<select> 태그의 주요 속성입니다. 마찬가지로 mapper에서 사용되는 주요 속성 명입니다. 암기합시다..!(저는 사실보면서 했어요~~헤헤)
 
 
 
05. Mybatis를 활용한 코드(쇼핑몰상품 Select / Update 해보기)
가. 개발 규격

 
이번 실습에서 개발할 규격입니다. goods(상품) TABLE 을 만들고 어노테이션을 사용하여 컴포넌트가 될 수 있게 만들며, mapper 클래스에 (select/insert/update) 가 사용될 수 있도록 설정합니다.(헤헤 지금 보니까 insert 문은 이번 실습에 사용 안했네 데헷🤣)
실습시작해보겠습니다..!
 
 
나. 구현 방법 (전체구성)
이번실습에서 사용한 환경입니다.
 
pakages : mybatis
                    org.kitri.springmybatis
                    org.kitri.springmybatis.controller
                    org.kitri.springmybatis.dao
                    org.kitri.springmybatis.dto
                   org.kitri.springmybatis.service
 
 
class :  mybatis.xml (요놈이 이번 Mybatis 실습에서 핵심인 mapper 역할을 합니다.)
              RunMain.java
              GoodsController.java
              GoodsDao.java
              GoodsDaoImpl.java
              Goods.java
              GoodsService.java
              GoodsServiceImpl.java
 
 
xml : config.xml
            pom.xml
            Goods.xml
 
 

 

 
 
 
 

pakages :  mybatis
Class : mybatis.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="org.kitri.springmybatis.dao.GoodsDao">

	<select id="findAllGoods"
		resultType="org.kitri.springmybatis.dto.Goods">
		SELECT * FROM goods
	</select>

	<select id="findGoodsByProductCode" parameterType="String"
		resultType="org.kitri.springmybatis.dto.Goods">
		SELECT * FROM goods WHERE productCode = #{productCode}
	</select>

	<update id="updateQuantity" parameterType="map">
		UPDATE goods SET
		quantity = #{newQuantity} WHERE productCode = #{productCode}
	</update>

	<update id="updateProductStatus" parameterType="map">
		UPDATE goods SET
		productStatus = #{productStatus} WHERE productCode = #{productCode}
	</update>

</mapper>

 
이번 실습에서 가장 중요한 내용이여서 먼저 다루어 보겠습니다.  위쪽에서 select 주요 태그 구성을 참고하여 다음과 같이 select 문을 만들어 봤습니다. 
 
1. namespce 의 이름을 입력해서 외부에서로부터 접근할 수 있게 설정했습니다.
2. findAllGood : 모든 상품이 검색될 수 있는 select 문입니다.
3. findGoodsByProductCode : 상품코드를 인식할 수 있게 해주는 select 문입니다.
4. updateQuantity : quantity(상품수량)을 update 할 수 있게 해주는 문입니다.
5. updateProductStatus : productStatus(상품상태)를 update 할 수 있게 해주는 문입니다.
 
 
 
Class : pom.xml
 

 
 

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>org.kitiri</groupId>
	<artifactId>springmybatis</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>springcore</name>
	<!-- FIXME change it to the project's website -->
	<url>http://maven.apache.org</url>

	<properties>
		<springframework.version>4.3.6.RELEASE</springframework.version>
		<javax.annotation.version>1.3.2</javax.annotation.version>
		<junit.version>4.11</junit.version>
		<springmybatis.version>2.0.5</springmybatis.version>
		<mybatis.version>3.5.4</mybatis.version>
		<apache.common.dbcp.version>2.7.0</apache.common.dbcp.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>${springmybatis.version}</version>
		</dependency>

		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>${mybatis.version}</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>${apache.common.dbcp.version}</version>
		</dependency>


		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>${javax.annotation.version}</version>
		</dependency>

		<dependency>
			<groupId>com.oracle.database.jdbc</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0.4</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>5.3.2</version>
		</dependency>


		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.0</version>
					<configuration>
						<source>11</source>
						<target>11</target>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

 
이번실습에서는 pom.xml에 mybatis가 적용될 수 있도록 추가해줘야 하며, 저는 추가로 외부 라이브러리랑 프레임워크도 가져오기 위해서 web도 사용했습니다.
 
 
 
pakages :  org.kitri.springmybatis
Class : RunMain.java

package org.kitri.springmybatis;

import org.kitri.springmybatis.controller.GoodsController;
import org.kitri.springmybatis.dto.Goods;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;
import java.util.Scanner;

public class RunMain {

    public static void main(String[] args) {
        try {
            // 스프링 컨테이너 생성
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/config.xml");

            // GoodsController 빈 객체를 가져옴
            GoodsController goodsController = ctx.getBean(GoodsController.class);

            // list 메서드 호출
            List<Goods> goodsList = goodsController.list();

            // 결과 출력
            System.out.println("상품 목록:");
            for (Goods goods : goodsList) {
                System.out.println(goods);
            }

            // 상품 추가 희망 번호 입력
            Scanner scanner = new Scanner(System.in);
            System.out.print("문의하기(상품추가 희망시 코드번호입력): ");
            String productCode = scanner.nextLine();

            
            if ("004".equals(productCode) ) {
                goodsController.updateQuantity();

                // 상품 추가 후 목록 다시 출력
                System.out.println("상품 추가 후 목록:");
                goodsList = goodsController.list();
                for (Goods goods : goodsList) {
                    System.out.println(goods);
                }
            } else {
                System.out.println("해당 상품번호로 등록된 상품이 없습니다.");
            }

            // 스프링 컨테이너 소멸
            ctx.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 
 
main () 클래스 입니다. 외부 클래스로부터 상품 목록을 볼 수 있게 구현했으며, 문의하기를 통해 상품코드를 입력하면 ipdate되게 설정했습니다.(저는 004만 update 되게 구현해봤습니다.)
 
 
 
 
pakages : org.kitri.springmybatis.controller
Class : GoodsController.java

 

package org.kitri.springmybatis.controller;

import org.kitri.springmybatis.dto.Goods;
import org.kitri.springmybatis.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/goods")
public class GoodsController {

	@Autowired
	private GoodsService goodsService;

	@GetMapping("/list")
	public List<Goods> list() {
		return goodsService.findAllGoods();
	}

	@GetMapping("/updateQuantity")
	public String updateQuantity() {
		Goods goods = goodsService.findGoodsByProductCode("004");
		if (goods != null) {
			int newQuantity = goods.getQuantity() + 50;
			goodsService.updateQuantity("004", newQuantity); // 상품 코드를 직접 전달
			System.out.println("문의하신 상품의 수량을 증가시켰습니다.");
		}
		return "redirect:/goods/list";
	}

}

 
마찬가지로 외부 클래스값을 받는 클래스입니다. 여기서는 GetMapping을 사용해서 이름을 정의한 다음 RunMain이 받을 수 있게 수정하였습니다. 또한, updateQuantity를 사용하여 상품코드004에 quantity(상품수량이) != null 이면 수량이 +50이 되도록 구현했습니다.
 
 
 
 
pakages :org.kitri.springmybatis.dao
Class : GoodsDao

 

package org.kitri.springmybatis.dao;

import org.kitri.springmybatis.dto.Goods;

import java.util.List;

public interface GoodsDao {
    List<Goods> findAllGoods();
    Goods findGoodsByProductCode(String productCode);
    void updateQuantity(String productCode, int newQuantity);
    void updateProductStatus(String productCode, String productStatus);
}

 
이 코드에서는 맨 처음 Good.xml 에서 mapping 해놓은 dao 클래스입니다. mybatis에서 정의해놓은 sql문을 받아주는 역할을 합니다.
 
 
Class : GoodsDaoImpl

 

package org.kitri.springmybatis.dao;

import org.apache.ibatis.session.SqlSession;
import org.kitri.springmybatis.dto.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

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

@Repository
public class GoodsDaoImpl implements GoodsDao {

    @Autowired
    private SqlSession sqlSession;

    @Override
    public List<Goods> findAllGoods() {
        return sqlSession.selectList("org.kitri.springmybatis.dao.GoodsDao.findAllGoods");
    }

    @Override
    public Goods findGoodsByProductCode(String productCode) {
        return sqlSession.selectOne("org.kitri.springmybatis.dao.GoodsDao.findGoodsByProductCode", productCode);
    }

    @Override
    public void updateQuantity(String productCode, int newQuantity) {
        Map<String, Object> parameterMap = new HashMap<>();
        parameterMap.put("productCode", productCode);
        parameterMap.put("newQuantity", newQuantity);
        sqlSession.update("org.kitri.springmybatis.dao.GoodsDao.updateQuantity", parameterMap);
    }

    @Override
    public void updateProductStatus(String productCode, String productStatus) {
        Map<String, Object> parameterMap = new HashMap<>();
        parameterMap.put("productCode", productCode);
        parameterMap.put("productStatus", productStatus);
        sqlSession.update("org.kitri.springmybatis.dao.GoodsDao.updateProductStatus", parameterMap);
    }
}

 
※ 여기가 바로 MyBatis 동작 구조 부분입니다. SqlSession 을 사용하여 SQL을 실행하고 결과를 매핑하게 해주는 역할을 해줍니다.
 
 
 
pakages :org.kitri.springmybatis.dto
Class : GoodsDto

package org.kitri.springmybatis.dto;

public class GoodsDto {
	private String productCode;
	private String productName;
	private String productPrice;
	private String manufacturer;
	private String productStatus;
	private int quantity;

	public String getProductCode() {
		return productCode;
	}

	public void setProductCode(String productCode) {
		this.productCode = productCode;
	}

	public String getProductName() {
		return productName;
	}

	public void setProductName(String productName) {
		this.productName = productName;
	}

	public String getProductPrice() {
		return productPrice;
	}

	public void setProductPrice(String productPrice) {
		this.productPrice = productPrice;
	}

	public String getManufacturer() {
		return manufacturer;
	}

	public void setManufacturer(String manufacturer) {
		this.manufacturer = manufacturer;
	}

	public String getProductStatus() {
		return productStatus;
	}

	public void setProductStatus(String productStatus) {
		this.productStatus = productStatus;
	}

	public int getQuantity() {
		return quantity;
	}

	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}

	@Override
	public String toString() {
		return "Goods{" + "productCode='" + productCode + '\'' + ", productName='" + productName + '\''
				+ ", productPrice='" + productPrice + '\'' + ", manufacturer='" + manufacturer + '\''
				+ ", productStatus='" + productStatus + '\'' + ", quantity=" + quantity + '}';
	}
}

 
항상 사용되는 get,set 그리고 toString () 을 사용하는 dto 클래스입니다. 출력값이 나오는 부분을 구현해줍니다.
 
 
pakages : org.kitri.springmybatis.service
Class : GoodsService

package org.kitri.springmybatis.service;

import org.kitri.springmybatis.dto.GoodsDto;
import java.util.List;

public interface GoodsService {
    List<GoodsDto> findAllGoods();
    GoodsDto findGoodsByProductCode(String productCode);
    void updateQuantity(String productCode, int newQuantity);
}

 
마찬가지로 외부 클래스를 받는 클래습니다.
 
Class : GoodsServiceImpl

package org.kitri.springmybatis.service;

import org.kitri.springmybatis.dao.GoodsDao;
import org.kitri.springmybatis.dto.GoodsDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class GoodsServiceImpl implements GoodsService {

    @Autowired
    private GoodsDao goodsDao;

    @Override
    public List<GoodsDto> findAllGoods() {
        return goodsDao.findAllGoods();
    }

    @Override
    public GoodsDto findGoodsByProductCode(String productCode) {
        return goodsDao.findGoodsByProductCode(productCode);
    }

    @Override
    @Transactional
    public void updateQuantity(String productCode, int newQuantity) {
        goodsDao.updateQuantity(productCode, newQuantity);
        if (newQuantity > 0) {
            goodsDao.updateProductStatus(productCode, "판매중");
        } else {
            goodsDao.updateProductStatus(productCode, "판매중지");
        }
    }
}

 
Dao 클래스의 값을 받는 클래스입니다. 여기서는 @Transactional 을 사용하여 트랜잭션을 시작하여 새로운 상품수량이 0보다 크면 상품상태가 판매중으로 나오게 설정했습니다. 
 
 
Class : config.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">

	<context:component-scan
		base-package="org.kitri.springmybatis" />

	<bean id="dataSource"
		class="org.apache.commons.dbcp2.BasicDataSource"
		p:driverClassName="oracle.jdbc.OracleDriver"
		p:url="jdbc:oracle:thin:@192.168.10.11:1521:DB19" p:username="dst04"
		p:password="dst04" />

	<bean class="org.mybatis.spring.SqlSessionFactoryBean"
		name="sqlSessionFactoryBean" p:dataSource-ref="dataSource"
		p:mapperLocations="classpath:/mybatis/*.xml"
		p:typeAliasesPackage="org.kitri.springmybatis.dto" />

	<bean class="org.mybatis.spring.SqlSessionTemplate"
		name="sqlSessionTemplate"
		c:sqlSessionFactory-ref="sqlSessionFactoryBean" />

</beans>

 
config.xml 파일입니다. 기존 실습과 동일하게 oracle 계정에 연동할수있게 해주고 하단에 mybatis 를 사용할 수 있게 해주는 sqlSession을 정의했습니다. 
 
 
 
다. 실행
모든 코드가 드디어 구성되었습니다...(휴) 이제 SQL 문과 연동시켜서 결과값을 확인해봅시다.
 
 

힘들다 힘들어...

 
 
 
 
다음은 goods(상품) TABLE 생성 SQL 문입니다.

 

Drop table goods;

CREATE TABLE goods (
    productCode VARCHAR(20),
    productName VARCHAR(20),
    productPrice VARCHAR(20),
    manufacturer VARCHAR(20),
    productStatus VARCHAR(20),
    quantity INT
);

INSERT INTO goods (productCode, productName, productPrice, manufacturer, productStatus, quantity)
VALUES ('001', '반팔 티셔츠', '25000', '나이키', '판매중', 100);
INSERT INTO goods (productCode, productName, productPrice, manufacturer, productStatus, quantity)
VALUES ('002', '청바지', '55000', '아디다스', '판매중', 80);
INSERT INTO goods (productCode, productName, productPrice, manufacturer, productStatus, quantity)
VALUES ('003', '긴팔 티셔츠', '45000', '퓨마', '판매중', 60);
INSERT INTO goods (productCode, productName, productPrice, manufacturer, productStatus, quantity)
VALUES ('004', '가디건', '65000', '르꼬끄', '판매중지', 0);
INSERT INTO goods (productCode, productName, productPrice, manufacturer, productStatus, quantity)
VALUES ('005', '신발', '105000', '반스', '판매중', 70);


select * from goods;

commit;

 
저는 상품코드 004의 수량을 0으로 설정해서 판매중지인 상태로 만들었습니다!
 
 
 
이제 코드 실행해보겠습니다.

 
정상적으로 작동하는게 보이며 상품의 목록이 전부 보이게 됩니다. 이때 004의 quantity = 0 이여서 현재 판매중지 상태입니다. 
 
 

 
그래서 해당 상품코드인 "004"를 입력한 결과 수량이 50으로 증가 했으며, 상품상태도 판매중인것으로 바뀐것을 볼 수 있습니다.
 
 
 
 
 

신난다 신나...야호

'Spring' 카테고리의 다른 글

07. Spring - ★JDBCTemplate 연동(응용)★  (0) 2024.04.24
06. Spring - ★JDBCTemplate 연동★  (2) 2024.04.23
05. Spring - Interface 주입  (2) 2024.04.22
04. Spring- Auto Wiring(@Autowiring, @Qualifier)  (3) 2024.04.19
03. Spring- Properties  (3) 2024.04.18
2024. 5. 2. 17:26