<body>
<form action="/recipe/modify.do" method="post"
enctype="multipart/form-data">
<input type="hidden" name="recipeNo" value="${recipe.recipeNo }">
<div class="container-lg align-items-center">
<div class="container-lg col-sm-12 row align-items-center p-0">
<!-- 여기는 대표 이미지 박스 -->
<div class="col-md-5 col-sm-12 container-lg align-items-center">
<div class="row col-md-4 m-2 col-sm-12 align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
fill="currentColor" class="bi bi-x-circle-fill float-end"
onclick="mainPicDel()">
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z" />
</svg>
<label class="input-file-button float-start" for="input-file">
<img id="output" class="mx-auto " width="400px" height="270px"
src="/resources/recipeImg/${recipe.mainPicRename }"
style="background-color: gray; border-radius: 10px;">
</label> <input type="file" id="input-file" style="display: none"
accept="image/jpeg, image/png, image/jpg" name="mainPicture"
class="isFile" onchange="loadFile(event)" />
<!-- 수정 전 이미지이름 전송 -->
<input type="hidden" name="mainPicRename" value="${recipe.mainPicRename }">
<input type="hidden" name="mainPic" value="${recipe.mainPic }">
</div>
</div>
<div class="col-md-7 container-lg col-sm-12">
<div class="form-floating col-sm-12 ">
<input type="text" class="form-control" id="" name="recipeName"
value="${recipe.recipeName }"> <label for="floatingInput">레시피
제목</label>
</div>
<br>
<div class="form-floating col-sm-12 ">
<input type="text" class="form-control" id="" name="recipeVideo"
value="${recipe.recipeVideo }" onblur="isYoutube()"> <label
for="floatingInput">유튜브 링크</label>
</div>
<div class="mt-5 col-12">
<label for="validationCustom04" class="form-label"><h5>카테고리</h5></label>
<select class="form-select" id="" name="recipeCategory" required>
<option selected disabled value="">카테고리 선택</option>
<option value="mael"
<c:if test="${recipeCategory == mael}"> selected</c:if>>식사</option>
<option value="relish"
<c:if test="${recipeCategory == relish}"> selected</c:if>>술안주</option>
<option value="dessert"
<c:if test="${recipeCategory == dessert}"> selected</c:if>>간식</option>
<option value="drink"
<c:if test="${recipeCategory == drink}"> selected</c:if>>술/음료</option>
</select>
<div class="invalid-feedback">카테고리를 선택하세요</div>
<br>
<div class="form-floating align-items-center">
<input type="text" class="form-control mb-2" id=""
value="${recipe.recipeTime }" name="recipeTime"> <label
for="floatingInput">소요시간</label>
</div>
<div class="col-md-12 col-sm-12">
<h5>해시태그</h5>
<div class="overflow-hidden">
<label class="w-25 float-start"> <input
class="form-check-input" type="checkbox" name="jmt"
<c:if test="${rTag.jmt==true }">checked</c:if> value="true">
JMT
</label> <label class="w-25 float-start"> <input
class="form-check-input" type="checkbox" name="healthy"
<c:if test="${rTag.healthy==true }">checked</c:if> value="true">
건강한
</label> <label class="w-25 float-start"><input
class="form-check-input" type="checkbox" name="goodSpicy"
<c:if test="${rTag.goodSpicy==true }">checked</c:if>
value="true"> 맛있게 매운</label> <label class="w-25 float-start"><input
class="form-check-input" type="checkbox" name="soSpicy"
<c:if test="${rTag.soSpicy==true }">checked</c:if> value="true">
아주매운</label> <label class="w-25 float-start"><input
class="form-check-input" type="checkbox" name="sweet"
<c:if test="${rTag.sweet==true }">checked</c:if> value="true">
달콤한</label> <label class="w-25 float-start"><input
class="form-check-input" type="checkbox" name="easy"
<c:if test="${rTag.easy==true }">checked</c:if> value="true">
간편한</label> <label class="w-25 float-start"><input
class="form-check-input" type="checkbox" name="full"
<c:if test="${rTag.full==true }">checked</c:if> value="true">
든든한</label> <label class="w-25 float-start"><input
class="form-check-input" type="checkbox" name="party"
<c:if test="${rTag.party==true }">checked</c:if> value="true">
파티용</label>
</div>
</div>
</div>
</div>
<br>
<div class=" row m-0 mt-3 mb-3 p-0 ">
<div class="form-floating">
<input type="text" class="form-control" id="" maxlength="30"
name="recipeInfo" value="${recipe.recipeInfo}"
required="required"> <label for="floatingInput">
간단한소개 (30자 미만)</label>
</div>
</div>
<!-- 재료 입력-->
<div class="container align-items-center">
<div class=" col-md-12 m-0 p-0">
<div class="row col-md-6 col-12 float-start p-3 me-1">
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=1 }"> value="${rmList.get(0).material }"</c:if>
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=1 }"> value="${rmList.get(0).material }"</c:if>
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
<div class="row col-md-6 col-12 float-start p-3 ms-1">
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=2 }"> value="${rmList.get(1).material }"</c:if>
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=2 }"> value="${rmList.get(1).amount }"</c:if>
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
<div class=" col-md-12">
<div class="row col-md-6 col-12 float-start p-3 me-1">
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=3 }"> value="${rmList.get(2).material }"</c:if>
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=3 }"> value="${rmList.get(2).amount }"</c:if>
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
<div class="row col-md-6 col-12 float-start p-3 ms-1">
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=4 }"> value="${rmList.get(3).material }"</c:if>
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=4 }"> value="${rmList.get(3).amount }"</c:if>
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
<div class=" col-md-12 border-bottom-1">
<div class="row col-md-6 col-12 float-start p-3 me-1">
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=5 }"> value="${rmList.get(4).material }"</c:if>
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=5 }"> value="${rmList.get(4).amount }"</c:if>
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
<div class="row col-md-6 col-12 float-start p-3 ms-1">
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=6 }"> value="${rmList.get(5).amount }"</c:if>
name="material"> <label for="floatingInput">재료명</label>
</div>
<div class="form-floating col-md-6">
<input type="text" class="form-control" id="" maxlength="10"
<c:if test="${rmListSize >=6 }"> value="${rmList.get(5).amount }"</c:if>
name="amount"> <label for="floatingInput">재료수량</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="recipeDetail container row">
<!-- 여기서부터 레시피 설명-->
<!-- 레시피step forEach문시작 -->
<hr>
<c:forEach items="${rsList }" var="rStep">
<div class="REdetailC" id="REdetail">
<div class="row container p-3 float-start col-md-6 p-2 " id="">
<div class="form-floating col-md-12 p-0 pt-3">
<textarea class="form-control" name="recipeDescription"
placeholder="" id="floatingTextarea2" style="height: 250px">${rStep.recipeDescription }</textarea>
<label for="floatingTextarea2" class="mt-3">설명을 입력하세요</label>
</div>
<!-- 설명에 쉼표를 넣었을때 배열로 만들지 않기위한 더미 value -->
<input type="text" name="recipeDescription" value="ab22bb"
style="display: none">
</div>
<!-- 이미지 미리보기 이미지 파일 -->
<div class="row col-md-6 float-start p-2">
<div
class="col-md-5 col-sm-12 container-lg align-items-center m-0">
<div class="row col-md-4 col-sm-12 align-items-center">
<!-- 이미지 삭제 아이콘 -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
fill="currentColor" class="bi bi-x-circle-fill float-end"
onclick="PicDel(this, '${rStep.recipePicRename }', ${recipe.recipeNo })">
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z" />
</svg>
<label class="input-file-button float-start"> <img
class="detailImg mx-auto" width="400px" height="270px"
<c:if test="${rStep.recipePicRename ne null }">
src="/resources/recipeImg/${rStep.recipePicRename }"</c:if>
style="background-color: gray; border-radius: 10px;"> <input
type="file" name="recipePicModify" class="isFile"
style="display: none"
accept="image/jpeg, image/png, image/jpg"
onchange="imgView(this);">
</label>
</div>
</div>
</div>
</div>
<input type="text" name="recipePicRename" value="${rStep.recipePicRename}" style="display:none">
<input type="text" name="recipePic" value="${rStep.recipePic}" style="display:none">
</c:forEach>
<!-- 레시피step foreach문 종료 -->
<!-- 레시피 한블럭 설명종료 -->
<span id="addplace"></span>
</div>
<!-- 레시피 종료 -->
<!-- 설명추가 -->
<svg class="m-2" xmlns="http://www.w3.org/2000/svg" width="30"
height="30" fill="currentColor" class="bi bi-plus-circle-fill"
viewBox="0 0 16 16" onclick="addDe()">
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.5 4.5a.5.5 0 0 0-1 0v3h-3a.5.5 0 0 0 0 1h3v3a.5.5 0 0 0 1 0v-3h3a.5.5 0 0 0 0-1h-3v-3z" />
</svg>
<!-- 설명 삭제 -->
<svg class="m-2" xmlns="http://www.w3.org/2000/svg" width="30"
height="30" fill="currentColor" class="bi bi-dash-circle-fill"
viewBox="0 0 16 16" onclick="removeDe()">
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM4.5 7.5a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1h-7z" />
</svg>
<div class="col-md-12">
<input type="submit" value="수정" onclick="checkMainPic();">
</div>
</div>
</form>
</div>
<script>
//유튜브 링크 유효성체크//
var youUrl = /(http:|https:)?(\/\/)?(www\.)?(youtube.com|youtu.be)\/(watch|embed)?(\?v=|\/)?(\S+)?/g;
function isYoutube() {
var youtube = document.querySelector('[name="recipeVideo"]');
if (!youUrl.test(youtube.value)) {
alert("유튜브 주소는 embed이 포함된 고유주소로 입력해주세요")
youtube.value = "";
}
}
///설명 추가/삭제////
var detailForm = document.querySelector('#REdetail');
var addplace = document.querySelector('#addplace');
var count = document.querySelectorAll('.REdetailC').length+1;
var firstCount = document.querySelectorAll('.REdetailC').length+1;
function addDe() {
if (count <= 10) {
count++;
addplace.appendChild(detailForm.cloneNode(true));
document.querySelectorAll('.REdetailC')[document
.querySelectorAll('.REdetailC').length - 1].childNodes[1].childNodes[1].childNodes[1].value = "";
document.querySelectorAll('.REdetailC')[document
.querySelectorAll('.REdetailC').length - 1].childNodes[5].childNodes[1].childNodes[1].childNodes[5].childNodes[1].src = "";
}
}
function removeDe() {
var detailFormClass = document.querySelectorAll('.REdetailC');
if (count > firstCount) {
detailFormClass[detailFormClass.length - 1].remove();
count--;
}
}
function loadFile(event) {
var output = document.getElementById('output');
output.src = URL.createObjectURL(event.target.files[0]);
output.onload = function() {
URL.revokeObjectURL(output.src) // free memory
};
imgCheck()
};
///// 이미지파일 체크 시작 ////
var imgFile = document.querySelectorAll('.isFile');
var fileForm = /(.*?)\.(jpg|jpeg|png|gif|bmp)$/i;
var fileSize;
function checkMainPic() {
if (imgFile[0].value == "") {
alert("대표 이미지를 새로 설정하지 않으면 이미지가 그대로 출력됩니다");
}
};
function imgCheck() {
for (var i = 0; i < imgFile.length; i++) {
if (imgFile[i].value != "") {
if (!imgFile[i].value.match(fileForm)) {
alert("이미지 파일만 업로드 가능");
imgFile[i].value = "";
}
}
}
};
/////이미지 확장자 체크 종료///
function imgView(obj) {
var imgid = obj.previousElementSibling;
imgid.src = URL.createObjectURL(event.target.files[0]);
imgid.onload = function() {
URL.revokeObjectURL(imgid.src); // free memory
}
imgCheck()
};
function mainPicDel() {
imgFile[0].value = "";
output.removeAttribute('src');
}
function PicDel(obj,picName,recipeNo) {
var imgfiles = obj.nextElementSibling.childNodes[1];
var imgfilesinput = obj.nextElementSibling.childNodes[3];
if(imgfiles.src == null || imgfiles.src ==''){
alert("삭제할 이미지가 없습니다")
}else{
if(confirm("이미지를 삭제하시겠습니까? 삭제하면 복구할수 없고 현재페이지가 새로고침됩니다")){
event.preventDefault()
imgfilesinput.value = "";
imgfiles.removeAttribute('src');
location.href = "/recipe/imgRemove.do?picName="+picName+"&recipeNo="+recipeNo
}
}
}
//재료 유효성 검사//
var check = /,/
function materialCheck(obj){
if(check.test(obj.value)){
alert(",는 사용할수 없습니다.");
obj.value="";
}
}
</script>
//재료 유효성 검사//
var check = /,/
function materialCheck(obj){
if(check.test(obj.value)){
alert(",는 사용할수 없습니다.");
obj.value="";
}
}
/**
* 레시피 수정
*
* @param recipe
* @param rStep
* @param rMaterial
* @param rTag
* @param mv
* @param mainPicture
* @param recipePicture
* @param session
* @param request
* @return
*/
@RequestMapping(value = "/recipe/modify.do", method = RequestMethod.POST)
public ModelAndView modifyRecipe(@ModelAttribute Recipe recipe, @ModelAttribute RecipeStep rStep,
@ModelAttribute RecipeMaterial rMaterial, @ModelAttribute RecipeTag rTag, ModelAndView mv,
@RequestParam(value = "mainPicture", required = false) MultipartFile mainPicture,
@RequestParam(value = "recipePicModify", required = false) List<MultipartFile> recipePicture,
@RequestParam("recipeNo") Integer recipeNo, HttpSession session, HttpServletRequest request) {
try {
// 대표 이미지 교체
String mainPic = mainPicture.getOriginalFilename();
if (mainPicture != null && !mainPic.equals(""))// 새로 파일을 올렸을때, 이름이 없는 파일이 있을 경우를 생각해 null체크 2번함
{// 수정 할경우 대체/ 삭제 후 등록/ 대체는 어려워서 삭제후 등록으로 한다
String root = request.getSession().getServletContext().getRealPath("resources");// 저장된 파일의 경로를 가져온다.
String savedPath = root + "\\recipeImg"; // 가져온 경로에 업로드 파일이 들어있는 폴더의 경로까지 더해줌
File file = new File(savedPath + "\\" + recipe.getMainPicRename()); // 이미 저장한 파일의 이름을 가져와야 한다.
if (file.exists()) { // 지정한 파일이 있는지 없는지 체크
file.delete(); // 있으면 삭제
}
////////// 여기부터 파일 재 업로드/////////////////////
// 파일 이름으로 업로드하면 파일이름이 겹치면 파일이 겹쳐서 사라진다.
// 고유한 rename으로 변경해주어야 한다.
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String mainPicRename = sdf.format(new Date(System.currentTimeMillis())) + "."
+ mainPic.substring(mainPic.lastIndexOf(".") + 1);
mainPicture.transferTo(new File(savedPath + "\\" + mainPicRename));
recipe.setMainPic(mainPic);
recipe.setMainPicRename(mainPicRename);
recipe.setRecipeNo(recipeNo);
}
// 대표 이미지 교체 끝
int result = rService.modifyOneRecipe(recipe); // 레시피 메인테이블
// 레시피 재료 리스트 만들어서 전달하기
ArrayList<RecipeMaterial> rmList = new ArrayList<RecipeMaterial>();
String amount[] = rMaterial.getAmount().split(",");
String material[] = rMaterial.getMaterial().split(",");
for (int i = 0; i < material.length; i++) {
if (!amount[i].equals("") && !material[i].equals("")) {
// 재료나 수량이 비어있지 않을때만 List에 저장
RecipeMaterial rMaterialOne = new RecipeMaterial();
rMaterialOne.setAmount(amount[i]);
rMaterialOne.setMaterial(material[i]);
rMaterialOne.setMaterialOrder(i + 1);
rMaterialOne.setRecipeNo(recipeNo);
rmList.add(rMaterialOne);
}
}
int result1 = rService.modifyOneRecipeMaterial(rmList);// 레시피 재료 테이블
// 레시피 태그 true false로 받음
int result3 = rService.modifyOneRecipeTag(rTag);
// 레시피 순서 리스트 만들어서 전달하기
ArrayList<RecipeStep> rsList = new ArrayList<RecipeStep>();
rStep.getRecipeDescription();
String arrDescription[] = rStep.getRecipeDescription().split(",ab22bb,");
// 더미 value까지 배열을 나누는것으로 인식해서 사용자가 ,를 입력했을때 정상적으로 table에 저장되게 한다
arrDescription[arrDescription.length - 1] = arrDescription[arrDescription.length - 1].replace(",ab22bb",
"");
// 배열의 마지막은 ,가 안들어가기때문에 더미vlaue 배열값으로 인식한다, ,가 없는 더미value를 삭제 해주는 코드
// 레시피 이미지 교체
String root = request.getSession().getServletContext().getRealPath("resources");
String savedPath = root + "\\recipeImg";
String recipeRe[] = rStep.getRecipePicRename().split(",");
// 반복문으로 삭제/저장
for (int i = 0; i <arrDescription.length; i++) {
String recipePic = recipePicture.get(i).getOriginalFilename();
System.out.println(recipePic+","+i);
if (recipePicture.get(i) != null && !recipePic.equals("")) {
File file = new File(savedPath + "\\" + recipeRe); // 이미 저장한 파일의 이름을 가져와야 한다.
if (file.exists()) { // 지정한 파일이 있는지 없는지 체크
file.delete(); // 있으면 삭제
}
////////// 여기부터 파일 재 업로드/////////////////////
// 파일 이름으로 업로드하면 파일이름이 겹치면 파일이 겹쳐서 사라진다.
// 고유한 rename으로 변경해주어야 한다.
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String recipePicRename = sdf.format(new Date(System.currentTimeMillis())) + "rstep" + i + "."
+ recipePic.substring(recipePic.lastIndexOf(".") + 1);
recipePicture.get(i).transferTo(new File(savedPath + "\\" + recipePicRename));
// 여기서부터 레시피 step 테이블에 저장할 값 List화 시키는 코드
RecipeStep rStepOne = new RecipeStep();
if (i < arrDescription.length) {
if (!arrDescription[i].equals("")) {
rStepOne.setRecipeDescription(arrDescription[i]);
}
}
rStepOne.setRecipePic(recipePic);
rStepOne.setRecipePicRename(recipePicRename);
rStepOne.setRecipeOrder(i + 1);
rStepOne.setRecipeNo(recipeNo);
rsList.add(rStepOne);
}
} // 레시지 저장 반복문 종료
int result2 = rService.modifyOneRecipeStep(rsList); // 레시피 순서저장 코드 종료
mv.setViewName("redirect:/recipe/recipeList.do");
} catch (Exception e) {
e.printStackTrace();
mv.addObject("msg", e.getMessage());
mv.setViewName("common/error");
}
return mv;
}
레시피 재료는 첫번째칸에 쓴건 번호1 3번째 칸에 쓴건 번호3으로 인식하여 등록되지만 수정에서는 쓰지 않은 나머지 번호는 불러오지 않고 1,2 칸만 채우는 것이다.
그렇게 되면 재료1,3외에 다른 것은 쿼리문 update로는 수정할수 없는 문제가 있었다 (왜냐하면 2는 등록되어있지 않으니 2재료를 입력해도 update문은 되지 않는다)
- 이 문제는 레시피 입력창에서 재료 순서를 for문 i로 설정하는것이 가장 큰문제였는데, 그 문제를 해결하기 위해 재료 순서는 i가 아니라 입력된 입력된 그 숫자와 순서만큼으로 인식하게 하여 해결했다
- 다음 문제인 순서를 지나면 update를 할수 없는 문제는 다른 방식으로 해결했는데..
- 이번에는 service는 별로 중요하지 않으니 store만 공개할까 한다.
### Store
```java
/** 레시피 재료 수정 */
@Override
public int updateOneRecipeMaterial(SqlSessionTemplate session, List<RecipeMaterial> rmList) {
int result = 0;
for (int i = 0; i < rmList.size(); i++) {
result += session.update("RecipeMapper.updateOneMaterial", rmList.get(i));
}
if(result<rmList.size()) {
//null방지코드
for(int i=result; i<rmList.size(); i++) {
if(rmList.get(i).getAmount() == null) {
rmList.get(i).setAmount("");
}
if(rmList.get(i).getMaterial() == null) {
rmList.get(i).setMaterial("");
}
session.insert("RecipeMapper.insertRecipeMaterialPlus", rmList.get(i));
}
}
int count =session.selectOne("RecipeMapper.countMaterial",rmList.get(0).getRecipeNo());
if(count>rmList.size()) {
for(int i =rmList.size(); i<count; i++) {
HashMap<String, Integer> paraMap = new HashMap<String, Integer>();
paraMap.put("recipeNo", rmList.get(0).getRecipeNo());
paraMap.put("materialOrder", i);
result = session.delete("RecipeMapper.deleteOneMaterial",paraMap);
}
}
return result;
}
```
- if문을 활용해서 내가 가져온 재료의 순서만큼은 일반적으로 update하고 그 외에 다른값은 가져온 재료의 순서 size와 비교하여 size보다 많으면 insert문을 사용하여 새롭게 등록하였다
- 만약 내가 가지고온 재료 순서가 원래 등록된 재료 순서보다 적다면 나머지 재료 순서는 삭제해야 하기 때문에 count쿼리문을 이용하여 나머지 재료 순서는 삭제하도록 코드를 구성했다.
<insert id="insertRecipeMaterialPlus">
insert into recipe_material
values(#{materialOrder},#{recipeNo},#{material},#{amount})
</insert>
<update id = "updateOneMaterial">
update recipe_material set MATERIAL = #{material}, AMOUNT = #{amount}
where RECIPE_NO = #{recipeNo} and MATERIAL_ORDER = #{materialOrder}
</update>
<select id="countMaterial" resultType="_int">
select count(*) from recipe_material where RECIPE_NO = #{recipeNo}
</select>
<delete id="deleteOneMaterial">
delete recipe_material where RECIPE_NO = #{recipeNo} and MATERIAL_ORDER = #{materialOrder}
</delete>
countMaterial의 경우 resultType을 잘못써서 한참 오류가 났다. 잘 틀리는 부분이니 신경써야 할것 같다.
/** 레시피수정 */
@Override
public int updateOneRecipe(SqlSessionTemplate session, Recipe recipe) {
int result = session.update("RecipeMapper.updateOneRecipe", recipe);
return result;
}
/** 레시피 순서수정 */
@Override
public int updateOneRecipeStep(SqlSessionTemplate session, List<RecipeStep> rsList) {
int result = 0;
for (int i = 0; i < rsList.size(); i++) {
result += session.update("RecipeMapper.updateOneStep", rsList.get(i));
}
if(result<rsList.size()) {
for(int i=result; i<rsList.size();i++) {
result+= session.insert("RecipeMapper.insertRstepPlus",rsList.get(i));
}
}
return result;
}
/** 레시피 태그 수정 */
@Override
public int updateOneRecipeTag(SqlSessionTemplate session, RecipeTag rTag) {
int result = session.update("RecipeMapper.updateOneTag", rTag);
return result;
}
<update id = "updateOneRecipe">
update recipe_tbl set RECIPE_NAME = #{recipeName}, RECIPE_INFO = #{recipeInfo}, MAIN_PICTURE = #{mainPic}, RECIPE_CATEGORY= #{recipeCategory},
RECIPE_VIDEO = #{recipeVideo}, MAIN_PIC_RENAME = #{mainPicRename}, RECIPE_TIME = #{recipeTime}, UPDATE_DATE = default
where RECIPE_NO = #{recipeNo}
</update>
<update id = "updateOneStep">
update recipe_step set recipe_Description = #{recipeDescription}, RECIPE_PICTURE = #{recipePic}, RECIPE_PIC_RENAME= #{recipePicRename}
where RECIPE_NO = #{recipeNo} and RECIPE_ORDER = #{recipeOrder}
</update>
<update id = "updateOneMaterial">
update recipe_material set MATERIAL = #{material}, AMOUNT = #{amount}
where RECIPE_NO = #{recipeNo} and MATERIAL_ORDER = #{materialOrder}
</update>
<update id = "updateOneTag">
update recipe_tag set jmt = #{jmt}, healthy = #{healthy}, goodSpicy = #{goodSpicy}, full = #{full},soSpicy = #{soSpicy}, sweet = #{sweet},easy = #{easy},party = #{party}
where RECIPE_NO = #{recipeNo}
</update>
<insert id="insertRstepPlus">
insert into recipe_step values(#{recipeOrder},#{recipeNo},#{recipeDescription},#{recipePic},#{recipePicRename})
</insert>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${recipe.recipeName }</title>
</head>
<body>
<style>
#imgDiv {
width: 100%;
height: 500px;
overflow: hidden;
}
#mainImg {
width: 100%;
height: auto;
position: relative;
top: 10;
}
#article1 {
border-right: 1px solid lightgray;
margin: 0 auto;
text-align : center;
}
#article2 {
margin: 0 auto;
}
#title{
text-align : center;
}
#hashtag{
text-align : left;
}
#wirter-area{
text-align : right;
}
#other-recipe-area{
height:80%;
}
#list-icon{
position: fixed;
top: 6%;
left:6%;
z-index: 99;
}
#list-icon:hover, .p3:hover{
cursor:pointer
}
#step-img{
width:80%;
height:auto;
}
</style>
<section style="margin : 0 auto;">
<span id="list-icon-area">
<svg onclick="list();" id="list-icon" xmlns="http://www.w3.org/2000/svg" width="50" height="50" fill="currentColor" class="bi bi-arrow-left-circle-fill" viewBox="0 0 16 16">
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0zm3.5 7.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H11.5z"/>
</svg>
</span>
<div class=" container-lg">
<div id="imgDiv" class="" style="">
<img id="mainImg"
src="/resources/recipeImg/${recipe.mainPicRename }"
class="img-fluid" alt="...">
</div>
<div id="title" class="py-2 row" >
<h1>${recipe.recipeName }</h1>
<!-- 해쉬태그 영역 -->
<div id="hashtag" class="ps-5 col-md-10">
<h5> <c:if test="${rTag.jmt }">
#jmt
</c:if>
<c:if test="${rTag.healthy }">
#건강한
</c:if>
<c:if test="${rTag.goodSpicy }">
#맛있게 매운
</c:if>
<c:if test="${rTag.full }">
#든든한
</c:if>
<c:if test="${rTag.soSpicy }">
#아주 매운
</c:if>
<c:if test="${rTag.sweet }">
#달콤한
</c:if>
<c:if test="${rTag.easy }">
#간편한
</c:if>
<c:if test="${rTag.party }">
#파티용
</c:if>
</h5>
</div> <!-- 해쉬태그 영역종료 -->
<div id="button-area" class="col-md-2"><!-- 버튼영역 -->
<button class="btn btn-primary"
onclick="location.href='/recipe/modifyForm.do?recipeNo=${recipe.recipeNo }';">수정</button>
<button class="btn btn-primary" onclick="removeRecipe(${recipe.recipeNo });">삭제</button>
</div>
</div><!-- 타이틀 영역 -->
<hr>
<div class="col-md-12 m-0 row" >
<!-- 아티클 전체 들어감-->
<div class="col-md-8" id="article1"
><article>
<!-- 작성자 영역 -->
<div id="wirter-area" class="col-md-12" >
<h5>작성자 : ${recipe.memberEmail } ${recipe.recipeInfo } <button class="btn btn-danger">신고</button></h5>
</div><!-- 작성자 영역종료 -->
<!-- 비디오 영역 -->
<div id="youtube-area" class="col-md-12 p-3">
<!-- 비디오 주소를 입력했을때만-->
<c:if test="${recipe.recipeVideo ne null }">
<iframe width="560" height="315" src="${recipe.recipeVideo}"
title="YouTube video player" frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen></iframe>
</c:if>
</div>
<!--레시피 순서영역 -->
<div id="step-area" class="col-md-12">
<c:forEach items="${rsList }" var="rsList">
<c:if test="${rsList.recipePicRename ne null }">
<img id="step-img" src="/resources/recipeImg/${rsList.recipePicRename }">
<br>
</c:if>
<p> ${rsList.recipeDescription }</p>
</c:forEach>
</div><!-- 순서영역 종료 -->
<!-- 추천, 나만의 레시피 이이콘 영역 -->
<div id="recom-bookm-area" class="my-2">
<span id="heart" class="p-3 p3">
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" fill="red" class="bi bi-chat-heart" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M2.965 12.695a1 1 0 0 0-.287-.801C1.618 10.83 1 9.468 1 8c0-3.192 3.004-6 7-6s7 2.808 7 6c0 3.193-3.004 6-7 6a8.06 8.06 0 0 1-2.088-.272 1 1 0 0 0-.711.074c-.387.196-1.24.57-2.634.893a10.97 10.97 0 0 0 .398-2Zm-.8 3.108.02-.004c1.83-.363 2.948-.842 3.468-1.105A9.06 9.06 0 0 0 8 15c4.418 0 8-3.134 8-7s-3.582-7-8-7-8 3.134-8 7c0 1.76.743 3.37 1.97 4.6a10.437 10.437 0 0 1-.524 2.318l-.003.011a10.722 10.722 0 0 1-.244.637c-.079.186.074.394.273.362a21.673 21.673 0 0 0 .693-.125ZM8 5.993c1.664-1.711 5.825 1.283 0 5.132-5.825-3.85-1.664-6.843 0-5.132Z"/>
</svg> </span>
<span id="star" class="p-3 p3">
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" fill="orange" class="bi bi-star" viewBox="0 0 16 16">
<path d="M2.866 14.85c-.078.444.36.791.746.593l4.39-2.256 4.389 2.256c.386.198.824-.149.746-.592l-.83-4.73 3.522-3.356c.33-.314.16-.888-.282-.95l-4.898-.696L8.465.792a.513.513 0 0 0-.927 0L5.354 5.12l-4.898.696c-.441.062-.612.636-.283.95l3.523 3.356-.83 4.73zm4.905-2.767-3.686 1.894.694-3.957a.565.565 0 0 0-.163-.505L1.71 6.745l4.052-.576a.525.525 0 0 0 .393-.288L8 2.223l1.847 3.658a.525.525 0 0 0 .393.288l4.052.575-2.906 2.77a.565.565 0 0 0-.163.506l.694 3.957-3.686-1.894a.503.503 0 0 0-.461 0z"/>
</svg>
</span>
</div>
<!-- 추천, 나만의 레시피 이이콘 영역 종료 -->
</article>
</div> <!-- 아티클1 영역 종료 -->
<div class="col-md-4 m-0" id="article2">
<article>
<div id="material-area" class="m-3">
<h4 style="text-align:center">레시피 재료</h4>
<ul>
<c:forEach items="${rmList}" var="rmList">
<li>재료: ${rmList.material}, 수량 : ${rmList.amount}
</c:forEach>
</ul>
<hr>
</div>
<div id="recipe-time-area" class="m-3" style="text-align:center">
<h4>조리 시간</h4>
${recipe.recipeTime }
<hr>
</div>
<div id="other-recipe-area">
<h4 style="text-align:center">추천 레시피</h4>
</div>
</article>
</div>
</div>
<article id="reply-area">
<div id="article3-area">
<hr>
<div id="comment" class="row">
<div id="comment-picture" class="col-md-2 d-none d-md-inline"> <!-- 코맨트 사진영역 -->
<svg xmlns="http://www.w3.org/2000/svg" width="80%" height="80%" fill="currentColor" class="bi bi-person-bounding-box" viewBox="0 0 16 16">
<path d="M1.5 1a.5.5 0 0 0-.5.5v3a.5.5 0 0 1-1 0v-3A1.5 1.5 0 0 1 1.5 0h3a.5.5 0 0 1 0 1h-3zM11 .5a.5.5 0 0 1 .5-.5h3A1.5 1.5 0 0 1 16 1.5v3a.5.5 0 0 1-1 0v-3a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 1-.5-.5zM.5 11a.5.5 0 0 1 .5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 1 0 1h-3A1.5 1.5 0 0 1 0 14.5v-3a.5.5 0 0 1 .5-.5zm15 0a.5.5 0 0 1 .5.5v3a1.5 1.5 0 0 1-1.5 1.5h-3a.5.5 0 0 1 0-1h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 1 .5-.5z"/>
<path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm8-9a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/>
</svg>
</div> <!-- 코멘트 사진 영역 종료 -->
<div id="commnet-contens" class="col-md-10"><!-- 코멘트 내용 영역 -->
<div class="shadow-lg p-3 mb-5 bg-body rounded mt-4 text-justify">
<div id="comment-row" class="row">
<div id="comment-writer" class="col-md-10"><h4>작성자</h4></div>
<div id="comment-button" class="col-md-2" style="text-align:right"> 신고</div>
</div>
<div id="comment-text-area">
<span>- 20 October, 2018</span>
<br>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Accusamus numquam assumenda hic aliquam vero sequi velit molestias doloremque molestiae dicta?</p>
</div>
<div id="comment-delmodi-buttom-area"style="text-align:right">
<button class="btn btn-outline-primary">수정</button> <button class="btn btn-outline-primary">삭제</button>
</div>
</div>
</div><!-- 코멘트 내용영역종료 -->
</div><!-- 코멘트 내용 영역종료 -->
<div id="comment-write-area" class="row">
<div id="comment-textarea" class="col-md-11">
<div class="form-floating">
<textarea class="form-control" placeholder="Leave a comment here" id="floatingTextarea2" style="height: 100px"></textarea>
<label for="floatingTextarea2">Comments</label>
</div>
</div>
<div id="comment-button-area" class="col-md-1">
<button style="height:100%; width=100%;" class="btn btn-outline-primary">등록</button>
</div>
</div>
</div>
</article><!-- 아티클3 종료 -->
</div>
</article>
<!-- 아티클 전체 들어감 -->
</div>
<!-- 메인 내용 폼 전체 들어감 -->
</section>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous">
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
crossorigin="anonymous"></script>
</body>
<script>
function removeRecipe(recipeNo){
if(confirm("삭제 하시겠습니까? 삭제하면 복구할수 없습니다")){
location.href='/recipe/remove.do?recipeNo='+recipeNo;
}
}
function list(){
location.href='/recipe/recipeList.do';
}
</script>
</html>