[Spring] 기본 CRUD, View 출력

2025. 3. 26. 19:44·Web

[Spring 에서 CRUD]

1. 뷰에서 컨트롤러로 action 전달 

2. 컨트롤러에 빈 메소드 추가 후 테스트 

3. mapper.xml에 쿼리문 추가

4. 쿼리문 id복사 

5. mapper.java 인터페이스에 추가 

6. DAO에 추가 

7. 컨트롤러에서 사용 

macbook.html

강의 개설하는 view

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>과정 개설</title>
</head>
<body>
<script src="./macbook.js?v=1"></script>
<form id="frm" method="post" action="./macbook_ok.do">
과정구분 : 
<select name="class_part">
<option value="온라인 상시과정">온라인 상시과정</option> 
<option value="온라인 정규 과정">온라인 정규 과정</option> 
<option value="집합 과정">집합 과정</option> 
</select><br>
과정 카테고리 :
<select name="class_cate">
<option value="교육">교육</option>
<option value="보강">보강</option>
<option value="자격증">자격증</option>
</select><br>
과정명 : <input type="text" name="class_name"><br>
학습일수 : <input type="text" name="class_day"><br>
정가 : <input type="text" name="class_price"><br>
수강료 : <input type="text" name="class_sales"><br>
과정소개 : <textarea cols="100" rows="5" name="class_info"></textarea><br>
강사명 : <input type="text" name="class_teacher"><br>
학습목표 : <textarea cols="100" rows="5" name="class_object"></textarea><br>
강의 개강 여부 : <input type="radio" value="Y" name="class_use">개강
<input type="radio" value="N" name="class_use" checked>종강<br>
<input type="button" value="강의개설" onclick="save_class()">
</form>
</body>
</html>

 

macbook.java (Controller)

컨트롤러 : 강의 리스트 출력, 강의 생성, 강의 수정, 강의 삭제  

package spring_learning;

import java.io.PrintWriter;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class macbook {
	// 컨트롤러의 리소스 네임과 DAO의 레포지토리 이름이 같으면 됨 !
	// @Resource : new 클래스명 호출과 동일하게 작동, @Repository의 이름을 가져오는 역할
	// @Resource와 @Repository는 영혼의 단짝친구
	@Resource(name = "macbook_DAO") // resource는 new의 역할
	private macbook_DAO dao; // 하나의 모델인데 new 안써도 됨

	// 그럼 이렇게 DTO를 쓰면 this.를 이용해서 DTO를 사용 가능하게됨 !
	// 대신 매개변수와 변수 이름이 같으면 에러가 날 수도 있음 주의 !!
	@Resource(name = "macbook_DTO")
	private macbook_DTO mdto;

	// 과정 리스트 출력
	@GetMapping("/macbook_list.do")
	public String macbook_list(Model m) {
		// List<macbook_DTO> : DTO 형태의 배열로 생성하여, JSP로 전달
		List<macbook_DTO> classList = this.dao.macbook_select();
		System.out.println(classList.get(0).class_name);
		m.addAttribute("ea", classList.size());
		m.addAttribute("classList", classList);
		return null;
	}

	// 과정개설 메소드
	@PostMapping("/macbook_ok.do")
	public String macbook_ok(macbook_DTO dto, Model m) throws Exception {
		try {
			// dao : 쿼리문을 작동시키는 놈
			int result = this.dao.macbook_insert(dto);
			String msg = "";
			if (result > 0) {
				msg = "alert('과정이 올바르게 개설되었습니다.');" + "location.href='macbook_list.do';";
			}
			m.addAttribute("msg", msg);
		} catch (Exception e) {
		}
		return "load";
	}

	// 수정 페이지 출력
	@PostMapping("/macbook_modify.do")
	public String macbook_modify(@RequestParam("midx") String midx, Model m) {
		// @RequestParam("midx") => 둘의 이름이 같으면 생략가능 가끔 값이 안받아지면 쓰기
		// 단, 체크박스로 배열을 받을때는 리퀘스트 바디, 어트리뷰트 사용

		// @RequestParam("midx") : front의 midx를
		// String midx : 매개변수명을 이거로 받겠음! (아무거나 써도됨)

		// macbook_DTO의 setter에 값을 이관한 상황
		macbook_DTO onedata = this.dao.macbook_one(midx);
//		System.out.println(onedata.class_name); // DTO의 getter 메소드를 사용

		m.addAttribute("onedata", onedata); // JSTL로 값을 이관함

		return null;
	}

	// 과정을 수정하는 메소드
	@PostMapping("/macbook_modifyok.do")
	public String macbook_modifyok(macbook_DTO dto, Model m) {
		int result = this.dao.macbook_update(dto); // DAO로 값을 전송
//		System.out.println(result);
		String msg = "";
		if (result > 0) {
			msg = "alert('정상적으로 데이터가 수정되었습니다.');" + "location.href='./macbook_list.do';";
		} else {
			msg = "alert('error');" + "history.go(-1);";
		}
		m.addAttribute("msg", msg);
		return "load";
	}

	PrintWriter pw = null;
	
	/*
	Model과 HttpServletResponse는 함께 사용 불가
	두개의 인터페이스 역할이 같으므로 하나만 사용이 가능 
	*/
	// 개설된 과정을 삭제하는 메소드
	@PostMapping("/macbook_delete.do")
	//Model과 HttpServletResponse는 상극 => 둘중하나만 쓰기 res쓰면 해당페이지에 출력해서 다음 페이지로 안넘어감 / 모델쓰면 다음페이지에 출력
	public String macbook_delete(@RequestParam("midx") String midx, HttpServletResponse res) throws Exception {
		res.setContentType("text/html; charset=utf-8");
		this.pw = res.getWriter();
		int result = this.dao.macbook_delete(Integer.parseInt(midx));	//트캐 필요하긴함
		if(result > 0) {
			this.pw.print("<script>"
					+ "alert('올바르게 해당 과정을 삭제하였습니다');"
					+ "location.href='./macbook_list.do';"
					+ "</script>");
		}
		pw.close();
		
		return null;
	}

}
  • xml정보 끌고오는 애들 Autowired, Inject
    •  @Autowired @Inject : 의존성 주입 XML=>Java, Java=>XML
    •  @Autowired SqlSessionFactory sqlfact;
  • ibatis로 연결
    •  @Inject SqlSessionFactory sqlfact;

src/main/resource/META-INF/mapper.xml

사용할 쿼리문을 작성하는 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="spring_learning.macbook_mapper">

<!-- 과정 insert -->
<insert id="macbook_insert">
insert into macbook_class (midx,class_part,class_cate,class_name,class_day,class_price,class_sales,class_info,class_teacher,class_object,class_use,today)
values ('0',#{class_part},#{class_cate},#{class_name},#{class_day},#{class_price},#{class_sales},#{class_info},#{class_teacher},#{class_object},#{class_use},now())
</insert>

<!-- 과정 하나의 데이터 -->
<select id="macbook_one" resultType="macbookdto" parameterType="String"> <!-- id로 받은 데이터 저장하는게 resultType -->
select * from macbook_class where midx=#{midx}
</select>

<!-- 과정 전체의 리스트 데이터 -->
<!-- resultType : config.xml에서 셋팅된 alias를 이용하여 Model DTO에 이관 -->
<select id="macbook_select" resultType="macbookdto">
select * from macbook_class order by midx desc
</select>

<!-- 과정 데이터 수정 -->
<update id="macbook_update">
update macbook_class set class_part=#{class_part}, class_cate=#{class_cate}, 
class_name=#{class_name }, class_day=#{class_day }, class_price=#{ class_price}, 
class_sales=#{class_sales }, class_info=#{class_info }, class_teacher=#{class_teacher },
 class_object=#{class_object }, class_use=#{class_use }
where midx=#{midx}
</update>

<!-- 과정 데이터 삭제 (자료형 int로 처리)-->
<delete id="macbook_delete" parameterType="int">
delete from macbook_class where midx=#{midx}
</delete>

</mapper>
  • SQL 문법에 대한 파일 (mapper)
    • namespace="spring_learning.koo"
      • spring_learning => 패키지명
      • koo 라는 Mapper 어노테이션을 찾음 
      • => mapper.xml과 koo.java를 연결시켜줌 
  • DML만 가능 (DDL, DCL 불가능 => 옛날처럼 커넥션으로 만드는 방법 밖에 없음)
    • < select>< /select>
    • < insert>< /insert>
    • < update>< /update>
    • < delete>< /delete>
  • xml에서는 세미콜론 안씀 !
    • ${} : 필드명, 테이블명, 파라미터
    • #{} : 값을 적용시킬때 사용하는 파라미터값 => 파라미터에 달러쓰면 보안개스렉이;
    • 좋은 예) 외따옴표가 필요없는 애는 달러 / 외따옴표가 필요한 애는 샵
    • select * from ${mrp} where mid=#{mid}; 
  • 과정 하나의 데이터 select
    • 매개변수 여러개 못받음
    • => 매개변수가 여러개일때는 배열이나 맵 하나로 받기! 
  • resultType을 쓸 수 있는 태그는 select밖에 없음 !

src/main/java/패키지/macbook_mapper.java (Mapper Interface)

package spring_learning;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface macbook_mapper {
	public macbook_DTO macbook_one(String midx);	//하나의 데이터만 가져옴 
	public int macbook_insert(macbook_DTO dto);		//신규 데이터 입력 
	public List<macbook_DTO> macbook_select();		//전체 데이터 
	public int macbook_update(macbook_DTO dto);		//과정 수정
	public int macbook_delete(int midx);			//삭제 (숫자로 처리)
}

 

  • @Mapper : mapper.xml에 있는 namespace와 연동, 메소드를 실행시키는 id와 연동 시키는 interface
    • ⭐️Mapper.xml에서 사용하는 id기준으로 메소드 이름을 설정 
    • 인터페이스 안 메소드명은 mapper.xml의 id와 동일 => mapper는 연결고리
    • sql 쿼리문을 실행시킬 수 있도록 적용된 interface
    • 쿼리문 안에 #{}때문에 dto를 인자로 넣음
    • mapper.xml의 sql 쿼리문들을 @Mapper로 연결시켜 아이디로 작동시키는 인터페이스
    • 이녀석은 mapper.xml만 연결됨
  • mapper.xml 먼저 쿼리문 만들고 그 id를 이용해서 인터페이스에 올리기 

macbook_DAO.java

데이터 Access하는 역할

package spring_learning;

import java.util.List;

import javax.annotation.Resource;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;

//DAO : 데이터를 Access를 하는 역할 
@Repository("macbook_DAO") // @Repository : Model을 Controller에 호출시킴
public class macbook_DAO implements macbook_mapper {
	// implements macbook_mapper
	// 쓰고 컨스페로 자동으로 넣으면 짱좋음 기존에쓰던게있으면 @Override만 붙이면 됨

	// 맵퍼 인터페이스 로드하여 DAO작성

	// mybatis로 db연결
	@Resource(name = "template")
	public SqlSessionTemplate st;

	// 하나의 데이터만 가져오는 메소드
	@Override
	public macbook_DTO macbook_one(String midx) {
		// setter형태로 DB에 있는 데이터를 이관
		// selectOne("mapper.xml 의 id", 매개변수)
		macbook_DTO onedata = this.st.selectOne("macbook_one", midx); // mapper.xml 의 id
		return onedata;
		// 하나만 가져오지만 아래 메소드처럼 selectList로 써도됨
	}

	//과정 생성 메소드 
	@Override
	public int macbook_insert(macbook_DTO dto) {
		int result = this.st.insert("macbook_insert", dto); // st. 컨스페 > sqlsesstion template용 선택
		return result;
	}

	// 전체 리스트 출력 메소드
	@Override
	public List<macbook_DTO> macbook_select() {
		// selectOne : 데이터 한개만 가져올 때 (dto, List배열, ArrayList, Map 등등 다 가능)
		// selectList : 데이터 여러개를 가져올 때 (List배열로 가져옴)
		List<macbook_DTO> classList = this.st.selectList("macbook_select");
		return classList;
	}

	// 데이터 수정 메소드
	@Override
	public int macbook_update(macbook_DTO dto) {
		int result = this.st.update("macbook_update", dto);
		return result;
	}

	// 데이터 삭제 메소드
	@Override
	public int macbook_delete(int midx) {
		int result = this.st.delete("macbook_delete", midx);
		return result;
	}

}
    • DAO : 데이터를 Access를 하는 역할 
    • @Repository : Model을 Controller에 호출시킴
      • Controller에서 @Resource를 이용하여 호출 (new의 역할)
  • implements macbook_mapper
    • 먼저 만든 Mapper interface를 implements로 구현
    • 컨트롤 + 스페이스바 사용하여 오버라이드하기
  •  mybatis로 db연결
    • @Resource(name = "template")
      public SqlSessionTemplate st;
  • DAO 작성 후 Controller에서 해당 메소드 호출하여 사용

나머지 view들

macbook_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="cr" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>과정 개설 리스트</title>
</head>
<body>
<p>개설된 과목 갯수 : ${ea }</p>
<!-- DTO에 있는 변수명으로 JSTL로 출력하는 형태 -->
<cr:forEach var="cdata" items="${classList }">
과정명 : ${cdata['class_name']}, 
강사명 : ${cdata.class_teacher}, 
수강료 : ${cdata.class_price}
<input type="button" value="수정" onclick="macbook_modify('${cdata.midx}')">
<input type="button" value="삭제" onclick="macbook_del('${cdata.midx}')">
<br>
</cr:forEach>

<!-- 
POST : 해당 게시물의 고유값을 POST Backend 전송
		따로 폼만들어서 보내기
		이것도 보안뚫림 : 개발자도구에서 히든값 바꿀수있음 
		=> innerHtml 만들기
 -->
 
 <!-- 
 form으로 post전송
 form하나로 함수 두개 사용 => js에서 action값 넣기 
 -->
<form id="frm" method="post" action="">
<input type="hidden" name="midx" value="">
</form>
 
 <!-- 
 <div id="msg"></div>
  -->

</body>
<script>
function macbook_modify(n){
	//Post 통신 (form)
	frm.midx.value=n;
	frm.action="./macbook_modify.do";
	frm.submit();
	
	//실무용 POST 전송 
	//해커가 수정할 틈 없이 전송됨 -> 보안 good
	/*
	var m = document.getElementById("msg");
	m.innerHTML = `<form id="frm" action="./macbook_modify.do">
        <input type="hidden" name="midx" value="`+n+`">
        </form>`;
	frm.submit();
	*/
	
	//GET : 빠르지만 눈에 보임 
	//location.href='./macbook_modify.do?midx='+n;
	//데이터를 여러개 붙일 경우 (+'&data='+n1+...); 실수마니생김 
	//=> 그냥 form 으로 hidden 써서 get으로 넘겨도 됨 
}
function macbook_del(n){
	if (confirm('해당 과정을 삭제하시겠습니까?\n삭제시 데이터는 복구되지 않습니다.')) {
			frm.midx.value = n;
			frm.action = "./macbook_delete.do";
			frm.submit();
		}
	}
</script>
</html>
  • 고수의 post 전송

macbook_modify.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="cr" uri="http://java.sun.com/jsp/jstl/core" %>
 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>과정 수정 페이지</title>
</head>
<body>
<script src="./macbook.js?v=1"></script>
<form id="frm" method="post" action="./macbook_modifyok.do">
<!-- 
수정 또는 삭제시 무조건 고유값 필요 
이거 안담으면 안됨 ! 
-->
<input type="hidden" name="midx" value="${onedata.midx}">
<!-- 1. front에서 js로 찍기 -->
과정구분 : 
<select name="class_part">
<option value="온라인 상시과정">온라인 상시과정</option> 
<option value="온라인 정규 과정">온라인 정규 과정</option> 
<option value="집합 과정">집합 과정</option> 
</select><br>

<!-- 
2. back이 JSTL로 찍기
배열이었다면 forEach 사용
지금은 따로따로 되어있어서 각각 집어넣음  
-->
과정 카테고리 : 
<select name="class_cate">
<option value="교육" 
	<cr:if test = "${onedata.class_cate} =='교육'}">selected</cr:if>
	>교육</option>
<option value="보강" 
	<cr:if test = "${onedata.class_cate} =='보강'}">selected</cr:if>
	>보강</option>
<option value="자격증" 
	<cr:if test = "${onedata.class_cate} =='자격증'}">selected</cr:if>
	>자격증</option>
</select><br>

<!-- 
input은 value에
textarea는 태그 사이에 
값 찍기 
-->
과정명 : <input type="text" name="class_name" value="${onedata.class_name}"><br>
학습일수 : <input type="text" name="class_day" value="${onedata.class_day}"><br>
정가 : <input type="text" name="class_price" value="${onedata.class_price}"><br>
수강료 : <input type="text" name="class_sales" value="${onedata.class_sales}"><br>
과정소개 : <textarea cols="100" rows="5" name="class_info">${onedata.class_info}</textarea><br>
강사명 : <input type="text" name="class_teacher" value="${onedata.class_teacher}"><br>
학습목표 : <textarea cols="100" rows="5" name="class_object">${onedata.class_object}</textarea><br>

<!-- 기존에 태그에 넣어져있던 checked 지우기 -->
강의 개강 여부 : 
<input type="radio" value="Y" name="class_use"
<cr:if test = "${onedata.class_use} =='Y'}">checked</cr:if>
>개강
<input type="radio" value="N" name="class_use"
<cr:if test = "${onedata.class_use} =='N'}">checked</cr:if>
>종강<br>

<input type="button" value="강의수정" onclick="save_class()">
</form>
</body>

<script>
//⭐.js 파일에서 Back-end 코드를 사용할 수 없음

window.onload = function(){
	//javascript 변수는 backend의 모든 변수값을 받을 수 있음
	var subject = "${onedata.class_part}";
	//console.log(subject);
	
	var ea = frm.class_part.length;
	console.log("ea : "+ea);
	console.log("value : "+frm.class_part.value);
	for(var f=0; f<ea; f++){
		if(frm.class_part[f].value == subject){
			frm.class_part[f].selected = "selected";	//체크박스면 checked
		}
	}
	
}

</script>
</html>
  • 수정 페이지
    • select
      • js를 이용하여 onload함수에서 반복문으로 처리
      • JSTL를 이용하여 배열일때 forEach를 사용해 처리
    • checkbox
      • jstl로 넘어온 값을 이용하여 if문으로 체크박스 체크 활성화 비활성화 

[Front에 script 찍기]

Model과 HttpServletResponse는 함께 사용 불가

두개의 인터페이스 역할이 같으므로 하나만 사용이 가능 

 

PrintWriter : 해당 페이지에 출력 => return에 다음 페이지 써놔도 안넘어감!

Model : 다음 페이지에 전달

1. PrintWriter (HttpServletResponse)

PrintWriter pw = null;
	public String macbook_delete(@RequestParam("midx") String midx, HttpServletResponse res) throws Exception {
		res.setContentType("text/html; charset=utf-8");
		this.pw = res.getWriter();
		int result = this.dao.macbook_delete(Integer.parseInt(midx));	//트캐 필요하긴함
		if(result > 0) {
			this.pw.print("<script>"
					+ "alert('올바르게 해당 과정을 삭제하였습니다');"
					+ "location.href='./macbook_list.do';"
					+ "</script>");
		}
		pw.close();
		return null;
	}

2. Model

@PostMapping("/macbook_modifyok.do")
	public String macbook_modifyok(macbook_DTO dto, Model m) {
		int result = this.dao.macbook_update(dto); // DAO로 값을 전송

		String msg = "";
		if (result > 0) {
			msg = "alert('정상적으로 데이터가 수정되었습니다.');" + "location.href='./macbook_list.do';";
		} else {
			msg = "alert('error');" + "history.go(-1);";
		}
		m.addAttribute("msg", msg);
		return "load";
	}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<script>
//Controller에서 Model로 전달된 값을 JSTL 변수 형태로 출력시키는 방식 
${msg}
</script>
저작자표시 비영리 변경금지 (새창열림)
'Web' 카테고리의 다른 글
  • [Spring] 체크박스 응용
  • [Spring] 추상클래스모델, 사용자정보 view
  • [API] JSON
  • [API] 메일전송
9na0
9na0
응애
  • 9na0
    구나딩
    9na0
  • 전체
    오늘
    어제
    • 분류 전체보기 (211)
      • Web (118)
      • Java (28)
      • 데이터베이스 (14)
      • 세팅 (12)
      • 과제 (3)
      • 쪽지시험 (2)
      • 정보처리기사 (4)
      • 서버 (25)
  • 블로그 메뉴

    • 링크

      • 포폴
      • 구깃
    • 공지사항

    • 인기 글

    • 태그

      file25
      net1
      net3
      notice_writer
      file24
      datalist
      io_dto
      net2
      exam1_1~10
      net4
      macbook pro m4
      spring-boot
      ab1
      re_java10
      Oracle
      noticewriteok
      file25_t
      java_io1~10
      net5~10
      re2
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    9na0
    [Spring] 기본 CRUD, View 출력
    상단으로

    티스토리툴바