스프링부트를 대략 알았으닝, 부트롱 RestFul CRUD를 한번 해보장!(흐름에 집중!)
File -> New -> Spring Starter Project를 눌러 아래와 같이 세팅한당.(jdk21기준)
Dependency는 아래와 같이 선택하도록 하장(오라클에 MyBatis를 쓸거당!)
Lombok은 요기서 다운받아서 실행시키는 요상한 설치법을 추가로 해주공
STS를 재 실행시켜줘야 한당.
요상태에서 바로 실행시켜보면 console에 아래와 같은 에러가 발생한당.
오라클 데이터베이스 연결과 MyBatis 설정이 필요하당.
application.properties 파일에 아래처럼 설정하장.(#은 주석 표시당당)
# 아래 2개는 참공
logging.level.com.e7e.merong=debug
#server.port=9004
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=java
spring.datasource.password=oracle
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.jdbc-type-for-null=varchar
mybatis.type-aliases-package=com.e7e.merong.vo
mybatis.mapper-locations=classpath:mybatis/mapper/*-Mapper.xml
# 아래도 파일업로드 용량설정이당 그냥 참고하장
# default 128K
#spring.servlet.multipart.max-file-size=10MB
#spring.servlet.multipart.max-request-size=12MB
#spring.servlet.multipart.file-size-threshold=12MB
위 설정대로 하기 위해 src/main/resources 아래에 mybatis/mapper 폴더를 맹글도록 하장.
다시 실행시켜보면 에러가 없어진 걸 알 수 있당.~~
본질을 흐리지 않고, 길에서 벗어나지 않도록 아래처럼 초 간단 테이블을 맹글장.
편의상 시퀀스도 1개 맹글장.
create SEQUENCE seq_sujin;
VO를 아래처럼 맹글장.(기본은 테이블 1개당 VO 1개로 추후 확장은 본인 선택이당!)
SujinVO.java
package com.e7e.merong.vo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@ToString
public class SujinVO {
private int sujinNum;
private String sujinName;
private String sujinContent;
private String sujinFile;
}
맵퍼 인터페이스를 아래 처럼 맹글장!
SujinMapper.java
package com.e7e.merong.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.e7e.merong.vo.SujinVO;
@Mapper
public interface SujinMapper {
// Get List
List<SujinVO> listSujin();
// Get One
SujinVO getSujin(SujinVO sujinVO);
// insert
int insertSujin(SujinVO sujinVO);
// update
int updateSujin(SujinVO sujinVO);
// delete
int deleteSujin(SujinVO sujinVO);
}
맵퍼 인퍼페이스와 매칭시킬 SQL문을 가진 맵퍼xml을 아래처럼 맹글장.
문제가 있당. sts4에 mybatis xml 틀을 만들어 주는 게 안 들어있당.(짜증)
메뉴 Help -> Eclipse Marketplace 에서 mybatis로 검색후 아래 플러그인을 설치하장
좋은 기능이 정말 많이 들어있엉, 생산성 차이가 극과 극이당.
Sujin-Mappr.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="com.e7e.merong.mapper.SujinMapper">
<select id="listSujin" resultType="SujinVO">
select * from sujin
</select>
<select id="getSujin" parameterType="SujinVO" resultType="SujinVO">
select * from sujin where sujin_num=#{sujinNum}
</select>
<insert id="insertSujin" parameterType="SujinVO">
insert into sujin(sujin_num,sujin_name,sujin_content,sujin_file)
values(seq_sujin.nextval,#{sujinName},#{sujinContent},#{sujinFile})
</insert>
<update id="updateSujin" parameterType="SujinVO">
UPDATE sujin
SET
sujin_name=#{sujinName},
sujin_content=#{sujinContent}
sujin_file=#{sujinFile}
WHERE
sujin_num=#{sujinNum}
</update>
<delete id="deleteSujin" parameterType="SujinVO">
delete from sujin where sujin_num=#{sujinNum}
</delete>
</mapper>
맵퍼는 서버를 돌려서 테스트하는 것 보다는 Spring 테스트에서 지원하는
Junit 테스트 프레임워크를 이용하는 것이 빠르고, 활용성도 좋아 정신 건강에 좋당.
src/test/java 패키지에 아래 파일을 맹글고, 마우스 오른쪽을 누르면 Run As에 Junit Test가 보인당.
SujinMapperTest.java
package com.e7e.merong;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.e7e.merong.mapper.SujinMapper;
import com.e7e.merong.vo.SujinVO;
@SpringBootTest
public class SujinMapperTest {
@Autowired
private SujinMapper sujinMapper;
@Test
@DisplayName("수진맵퍼테스통")
public void insertTest() {
SujinVO sujinVO = new SujinVO();
sujinVO.setSujinName("수진");
sujinVO.setSujinContent("그냥 웃지용");
sujinVO.setSujinFile("sujin.jpg");
assertEquals(1, sujinMapper.insertSujin(sujinVO));
}
}
실행시 아래와 같은 warin이 보일 수 있당.(무시해도 된당)
WARNING: A Java agent has been loaded dynamically (C:\Users\chlee\.m2\repository\net\bytebuddy\byte-buddy-agent\1.14.10\byte-buddy-agent-1.14.10.jar)WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warningWARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more informationWARNING: Dynamic loading of agents will be disallowed by default in a future releaseOpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
무시하시 싫다면 마우스 오른쪽 버튼 Run as -> Run Configuration에서 아래와 같이 해주면 눈에 가시가 빠진당
서비스 인터페이스를 맹글장.(여기애 @Service를 절대 붙이면 안된당!)
SujinService.java
package com.e7e.merong.service;
import java.util.List;
import com.e7e.merong.vo.SujinVO;
public interface SujinService {
// Get List
List<SujinVO> listSujin();
// Get One
SujinVO getSujin(SujinVO sujinVO);
// insert
int insertSujin(SujinVO sujinVO);
// update
int updateSujin(SujinVO sujinVO);
// delete
int deleteSujin(SujinVO sujinVO);
}
서비스 인터페이스틀 구현한 클래스를 맹글장.(여기에 @service를 붙여야 한당)
SujinServiceImple.java
package com.e7e.merong.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.e7e.merong.mapper.SujinMapper;
import com.e7e.merong.vo.SujinVO;
@Service
public class SujinServiceImpl implements SujinService{
@Autowired
private SujinMapper sujinMapper;
@Override
public List<SujinVO> listSujin() {
return sujinMapper.listSujin();
}
@Override
public SujinVO getSujin(SujinVO sujinVO) {
return sujinMapper.getSujin(sujinVO);
}
@Override
public int insertSujin(SujinVO sujinVO) {
return sujinMapper.insertSujin(sujinVO);
}
@Override
public int updateSujin(SujinVO sujinVO) {
return sujinMapper.updateSujin(sujinVO);
}
@Override
public int deleteSujin(SujinVO sujinVO) {
return sujinMapper.deleteSujin(sujinVO);
}
}
마지막으로 컨트롤러를 맹글고, Rest Client(부메랑, Postman등등...)를 이용 테스트한당.
SujinController.java
package com.e7e.merong.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.e7e.merong.service.SujinService;
import com.e7e.merong.vo.SujinVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequestMapping("/api")
public class SujinController {
@Autowired
private SujinService sujinService;
@GetMapping(value = "/sujins",produces = "application/json;charset=utf-8")
public List<SujinVO> listSujin(){
return sujinService.listSujin();
}
@GetMapping(value = "/sujin/{num}",produces = "application/json;charset=utf-8")
public SujinVO getSujin(@PathVariable int num){
SujinVO sujinVO = new SujinVO();
sujinVO.setSujinNum(num);
return sujinService.getSujin(sujinVO);
}
@PostMapping(value = "/sujin",produces = "application/json;charset=utf-8")
public int insertSujin(@RequestBody SujinVO sujinVO){
log.debug("" +sujinVO);
return sujinService.insertSujin(sujinVO);
}
@PutMapping(value = "/sujin",produces ="application/json;charset=utf-8")
public int updateSujin(@RequestBody SujinVO sujinVO){
return sujinService.updateSujin(sujinVO);
}
@DeleteMapping(value = "/sujin/{num}",produces ="application/json;charset=utf-8")
public int deleteSujin(@PathVariable int num){
SujinVO sujinVO = new SujinVO();
sujinVO.setSujinNum(num);
return sujinService.deleteSujin(sujinVO);
}
}
나는 잘된당.
백엔드는 대략 끝났으닝, 이제 프론트엔드만 맹글면 되겠당.~~
식사를 하시고 집으로 가는 길에 사진을 찍자고 하신당.
의식하지 못했당. 꾸미고 나오신 걸
머릿속이 하얗게 변했당. 영정사진!
배에 단단히 힘을 주고, 티 내지 않고 웃으며 같이 사진을 찍었당.
다시 일상으로 돌아갔당. 잊고 말았당.
얼마뒤 조용히 가시었당. 비가 온당.
엄마가 되어 보아야겠당.~~
https://www.youtube.com/watch?v=5C1OnNsEvKg
sts4 spring boot 세번쨍 (0) | 2023.07.10 |
---|---|
sts4 spring boot 첫번쨍 (0) | 2023.07.03 |