상품 삭제는 해당 상품이 이미 구입된 상품이 되어
조인된 테이블을 삭제할 수 없기 때문에
delete가 아닌 update를 통해서 삭제 여부를 체크하는 형식으로 변환하였다
상품에 수정은
사진 파일이 변경되지 않을 땐 기존 파일을 유지하고
사진 파일이 변경되었을 땐
- file 테이블 삭제 (file_group, file_detail)
- 기존 사진 파일도 삭제
- 새로운 파일을 저장
의 기능을 구현하도록 하였다.
허나 이 방식은 사진파일을 삭제해서 사진 파일을 아예 안들어가게 하거나
기존에 올렸던 파일을 부분적으로 삭제,
다른 사진과 함꼐 추가 등의 기능을 구현하지 않아 완전하지 않은 방식이라고 볼 수 있으며
해당 기능을 구현하는 방식을 생각해봐야겠다
JSP
detail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<script type="text/javascript" src="/resources/js/jquery.min.js"></script>
<!-- Default box -->
<div class="card card-solid">
<div class="card-body">
<div class="row">
<div class="col-12 col-sm-6">
<c:set var="prod" value="${buyer.prodVoList[0]}"/>
<h3 class="d-inline-block d-sm-none">${prod.prodName}</h3>
<div class="col-12">
<c:if test="${prod.fgvo.fileDetailVoList==null}">
<img src="/resources/images/noimage.jpg" class="product-image" alt="Product Image">
</c:if>
<c:if test="${prod.fgvo.fileDetailVoList!=null}">
<img src="${prod.fgvo.fileDetailVoList[0].fileSaveLocate}" class="product-image" alt="Product Image">
</c:if>
</div>
<div class="col-12 product-image-thumbs">
<c:forEach var="img" items="${prod.fgvo.fileDetailVoList}">
<div class="product-image-thumb" ><img src="${img.fileSaveLocate}" alt="Product Image" style="width: 100px"></div>
</c:forEach>
</div>
</div>
<div class="col-12 col-sm-6">
<h3 class="my-3">${prod.prodName}</h3>
<p>${buyer.buyerName}</p>
<hr>
${prod.prodOutline}
<!-- <h4>Available Colors</h4> -->
<!-- <div class="btn-group btn-group-toggle" data-toggle="buttons"> -->
<!-- <label class="btn btn-default text-center active"> -->
<!-- <input type="radio" name="color_option" id="color_option_a1" autocomplete="off" checked> -->
<!-- Green -->
<!-- <br> -->
<!-- <i class="fas fa-circle fa-2x text-green"></i> -->
<!-- </label> -->
<!-- <label class="btn btn-default text-center"> -->
<!-- <input type="radio" name="color_option" id="color_option_a2" autocomplete="off"> -->
<!-- Blue -->
<!-- <br> -->
<!-- <i class="fas fa-circle fa-2x text-blue"></i> -->
<!-- </label> -->
<!-- <label class="btn btn-default text-center"> -->
<!-- <input type="radio" name="color_option" id="color_option_a3" autocomplete="off"> -->
<!-- Purple -->
<!-- <br> -->
<!-- <i class="fas fa-circle fa-2x text-purple"></i> -->
<!-- </label> -->
<!-- <label class="btn btn-default text-center"> -->
<!-- <input type="radio" name="color_option" id="color_option_a4" autocomplete="off"> -->
<!-- Red -->
<!-- <br> -->
<!-- <i class="fas fa-circle fa-2x text-red"></i> -->
<!-- </label> -->
<!-- <label class="btn btn-default text-center"> -->
<!-- <input type="radio" name="color_option" id="color_option_a5" autocomplete="off"> -->
<!-- Orange -->
<!-- <br> -->
<!-- <i class="fas fa-circle fa-2x text-orange"></i> -->
<!-- </label> -->
<!-- </div> -->
<!-- <h4 class="mt-3">Size <small>Please select one</small></h4> -->
<!-- <div class="btn-group btn-group-toggle" data-toggle="buttons"> -->
<!-- <label class="btn btn-default text-center"> -->
<!-- <input type="radio" name="color_option" id="color_option_b1" autocomplete="off"> -->
<!-- <span class="text-xl">S</span> -->
<!-- <br> -->
<!-- Small -->
<!-- </label> -->
<!-- <label class="btn btn-default text-center"> -->
<!-- <input type="radio" name="color_option" id="color_option_b2" autocomplete="off"> -->
<!-- <span class="text-xl">M</span> -->
<!-- <br> -->
<!-- Medium -->
<!-- </label> -->
<!-- <label class="btn btn-default text-center"> -->
<!-- <input type="radio" name="color_option" id="color_option_b3" autocomplete="off"> -->
<!-- <span class="text-xl">L</span> -->
<!-- <br> -->
<!-- Large -->
<!-- </label> -->
<!-- <label class="btn btn-default text-center"> -->
<!-- <input type="radio" name="color_option" id="color_option_b4" autocomplete="off"> -->
<!-- <span class="text-xl">XL</span> -->
<!-- <br> -->
<!-- Xtra-Large -->
<!-- </label> -->
<!-- </div> -->
<div class="bg-gray py-2 px-3 mt-4">
<h2 class="mb-0">
<fmt:formatNumber value="${prod.prodSale}" pattern="#,###" type="number"/> 원
</h2>
</div>
<!-- <div class="mt-4"> -->
<!-- <div class="btn btn-primary btn-lg btn-flat"> -->
<!-- <i class="fas fa-cart-plus fa-lg mr-2"></i> -->
<!-- Add to Cart -->
<!-- </div> -->
<!-- <div class="btn btn-default btn-lg btn-flat"> -->
<!-- <i class="fas fa-heart fa-lg mr-2"></i> -->
<!-- Add to Wishlist -->
<!-- </div> -->
<!-- </div> -->
<button type="button" class="btn btn-primary btn-flat" onclick="javascript:location.href='/prod/edit?prodId=${prod.prodId}'" >
수정
</button>
<button type="button" class="btn btn-danger btn-flat" id="del">
삭제
</button>
<button type="button" onclick="javascript:location.href='/prod/list'" class="btn btn-default btn-lg btn-flat">
목록으로 돌아가기
</button>
<div class="mt-4 product-share">
<a href="#" class="text-gray">
<i class="fab fa-facebook-square fa-2x"></i>
</a>
<a href="#" class="text-gray">
<i class="fab fa-twitter-square fa-2x"></i>
</a>
<a href="#" class="text-gray">
<i class="fas fa-envelope-square fa-2x"></i>
</a>
<a href="#" class="text-gray">
<i class="fas fa-rss-square fa-2x"></i>
</a>
</div>
</div>
</div>
<div class="row mt-4">
<nav class="w-100">
<div class="nav nav-tabs" id="product-tab" role="tablist">
<a class="nav-item nav-link active" id="product-desc-tab" data-toggle="tab" href="#product-desc" role="tab" aria-controls="product-desc" aria-selected="true">Description</a>
<a class="nav-item nav-link" id="product-comments-tab" data-toggle="tab" href="#product-comments" role="tab" aria-controls="product-comments" aria-selected="false">Comments</a>
<a class="nav-item nav-link" id="product-rating-tab" data-toggle="tab" href="#product-rating" role="tab" aria-controls="product-rating" aria-selected="false">Rating</a>
</div>
</nav>
<div class="tab-content p-3" id="nav-tabContent">
<div class="tab-pane fade show active" id="product-desc" role="tabpanel" aria-labelledby="product-desc-tab">
${prod.prodDetail}
</div>
<div class="tab-pane fade" id="product-comments" role="tabpanel" aria-labelledby="product-comments-tab"> Vivamus rhoncus nisl sed venenatis luctus. Sed condimentum risus ut tortor feugiat laoreet. Suspendisse potenti. Donec et finibus sem, ut commodo lectus. Cras eget neque dignissim, placerat orci interdum, venenatis odio. Nulla turpis elit, consequat eu eros ac, consectetur fringilla urna. Duis gravida ex pulvinar mauris ornare, eget porttitor enim vulputate. Mauris hendrerit, massa nec aliquam cursus, ex elit euismod lorem, vehicula rhoncus nisl dui sit amet eros. Nulla turpis lorem, dignissim a sapien eget, ultrices venenatis dolor. Curabitur vel turpis at magna elementum hendrerit vel id dui. Curabitur a ex ullamcorper, ornare velit vel, tincidunt ipsum. </div>
<div class="tab-pane fade" id="product-rating" role="tabpanel" aria-labelledby="product-rating-tab"> Cras ut ipsum ornare, aliquam ipsum non, posuere elit. In hac habitasse platea dictumst. Aenean elementum leo augue, id fermentum risus efficitur vel. Nulla iaculis malesuada scelerisque. Praesent vel ipsum felis. Ut molestie, purus aliquam placerat sollicitudin, mi ligula euismod neque, non bibendum nibh neque et erat. Etiam dignissim aliquam ligula, aliquet feugiat nibh rhoncus ut. Aliquam efficitur lacinia lacinia. Morbi ac molestie lectus, vitae hendrerit nisl. Nullam metus odio, malesuada in vehicula at, consectetur nec justo. Quisque suscipit odio velit, at accumsan urna vestibulum a. Proin dictum, urna ut varius consectetur, sapien justo porta lectus, at mollis nisi orci et nulla. Donec pellentesque tortor vel nisl commodo ullamcorper. Donec varius massa at semper posuere. Integer finibus orci vitae vehicula placerat. </div>
</div>
</div>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
<script>
$(document).ready(function() {
$('.product-image-thumb').on('click', function () {
var $image_element = $(this).find('img')
$('.product-image').prop('src', $image_element.attr('src'))
$('.product-image-thumb.active').removeClass('active')
$(this).addClass('active')
})
})
$('#del').on('click',function(){
if(confirm("정말 삭제하시겠습니까?")){
location.href="/prod/delete?prodId=${prod.prodId}";
}
})
</script>
edit.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<link type="text/css" href="/resources/ckeditor5/sample/css/sample.css" rel="stylesheet" media="screen"/>
<script type="text/javascript" src="/resources/ckeditor5/ckeditor.js"></script>
<script type="text/javascript" src="/resources/js/jquery.min.js"></script>
<div class="card card-info">
<div class="card-header">
<h2>상품 수정</h2>
</div>
<c:set var="prod" value="${buyer.prodVoList[0]}"/>
<form id="frm" action="/prod/updatePost" method="post" enctype="multipart/form-data">
<div class="card-body">
<div class="row">
<div class="col-sm-6">
<!-- text input -->
<div class="form-group">
<label for="prodId">상품 코드</label> <input required type="text"
class="form-control" readonly placeholder="상품분류를 선택해주세요"
name="prodId" id="prodId" value="${prod.prodId}">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="prodLgu">상품 분류 코드</label> <select disabled="disabled" required="required" class="form-control"
id="prodLgu" name="prodLgu">
<c:forEach var="lprod" items="${lprod}">
<option value="${lprod.lprodGu}"
<c:if test="${prod.prodLgu==lprod.lprodGu}">selected</c:if>
>${lprod.lprodNm}</option>
</c:forEach>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<!-- text input -->
<div class="form-group">
<label for="prodName">상품 명</label> <input required type="text"
class="form-control" placeholder="상품명" name="prodName" value="${prod.prodName}"
id="prodName">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label for="prodBuyer">거래처</label> <select value="${prod.prodBuyer}" required class="form-control"
id="prodBuyer" name="prodBuyer">
<option value="">선택해주세요</option>
<c:forEach var="vo" items="${sel}">
<option value="${vo.buyerId}"
<c:if test="${prod.prodBuyer==vo.buyerId}">selected</c:if>
>${vo.buyerName}</option>
</c:forEach>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<!-- textarea -->
<div class="form-group">
<label for="prodSale">상품 판매가</label> <input required type="number"
class="form-control" placeholder="판매가" value="${prod.prodSale}" name="prodSale"
id="prodSale">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label>업로드 파일</label>
<div class="custom-file">
<input required type="file" class="custom-file-input" name="uploadFile"
id="uploadFile" multiple="multiple"> <label class="custom-file-label" id="fileLabel"
for="uploadFile">파일을 선택해주세요</label>
</div>
</div>
<div id="pImg">
<c:forEach var="img" items="${prod.fgvo.fileDetailVoList}">
<div class="image-container" style="display: inline-block; position: relative; margin: 5px;">
<img src="${img.fileSaveLocate}" style="width: 100px; border:1px solid #ced4da; border-radius: .25rem;" />
<!-- <button type="button" class="btn btn-tool" onclick="removeImage(this)" style="position: absolute; top: 5px; right: -1px; cursor: pointer;"> -->
<!-- <i class="fas fa-times"></i> -->
<!-- </button> -->
</div>
</c:forEach>
</div>
</div>
</div>
<!-- input states -->
<div class="form-group">
<label class="col-form-label" for="prodDetail">상품 상세 설명</label>
<div id="prodDetailTemp">${prod.prodDetail}</div>
<textarea hidden class="form-control" rows="3" id="prodDetail"
placeholder="상품 상세 설명" name="prodDetail" cols="">${prod.prodDetail}</textarea>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer row" style="justify-content: space-between;">
<div>
<a href="/prod/detail?prodId=${prod.prodId}" class="btn btn-info">취소</a>
</div>
<div>
<button type="submit" class="btn btn-warning">수정</button>
</div>
<div>
<button type="reset" id="reset" class="btn btn-secondary">초기화</button>
</div>
</div>
</form>
</div>
<script>
// uploadUrl => 이미지 업로드 시 요청할 요청URI
// editor => CKEditor가 생성된 후 바로 그 객체
// window.editor : 그 객체를 이렇게 부르겠다 정의
ClassicEditor.create( document.querySelector('#prodDetailTemp'),{ckfinder:{uploadUrl:'/image/upload'}})
.then(editor=>{window.editor=editor;})
.catch(err=>{console.error(err.stack);});
document.getElementById('uploadFile').addEventListener('change', function(event) {
const files = event.target.files; // 업로드된 파일 목록
const imagePreviewContainer = document.getElementById('pImg');
imagePreviewContainer.innerHTML = ''; // 기존 미리보기 초기화
// 업로드된 파일을 미리보기로 표시
for (let i = 0; i < files.length; i++) {
const file = files[i];
const reader = new FileReader();
reader.onload = function(e) {
const imgContainer = document.createElement('div');
imgContainer.className = 'image-container';
imgContainer.style.position = 'relative';
imgContainer.style.display = 'inline-block';
imgContainer.style.margin = '5px';
// 이미지 생성
const img = document.createElement('img');
img.src = e.target.result; // FileReader로 읽은 이미지 URL
img.style.width = '100px';
img.style.border = '1px solid #ced4da';
img.style.borderRadius = '.25rem';
// 삭제 버튼 생성
const button = document.createElement('button');
button.type = 'button';
button.className = 'btn btn-tool';
button.style.position = 'absolute';
button.style.top = '5px';
button.style.right = '-1px';
button.style.background = 'rgba(255, 255, 255, 0.8)';
button.style.border = 'none';
button.style.borderRadius = '50%';
button.style.padding = '2px';
button.style.cursor = 'pointer';
button.innerHTML = '<i class="fas fa-times"></i>';
// 삭제 버튼 클릭 시 동작
button.onclick = function() {
// 이미지 컨테이너 삭제
imgContainer.remove();
// 업로드된 파일 목록에서 해당 파일 삭제
const fileList = Array.from(document.getElementById('uploadFile').files);
const newFileList = fileList.filter((_, index) => index !== i); // 현재 인덱스 제외
const dataTransfer = new DataTransfer(); // 새로운 파일 리스트 생성
newFileList.forEach(file => dataTransfer.items.add(file)); // 새로운 파일 리스트 추가
document.getElementById('uploadFile').files = dataTransfer.files; // 파일 입력 필드 업데이트
};
// 이미지 컨테이너에 이미지와 버튼 추가
imgContainer.appendChild(img);
imgContainer.appendChild(button);
imagePreviewContainer.appendChild(imgContainer);
};
reader.readAsDataURL(file); // 파일을 데이터 URL로 읽기
}
});
function removeImage(button) {
// Find the parent container of the button
const imageContainer = button.closest('.image-container');
// Remove the image container from the DOM
if (imageContainer) {
imageContainer.remove();
}
}
$(function(){
window.editor.setData("${prod.prodDetail}");
$(".ck-blurred").keydown(function(){
console.log("str : " + window.editor.getData());
$("#prodDetail").val(window.editor.getData());
});
$(".ck-blurred").on("focusout",function(){
$("#prodDetail").val(window.editor.getData());
});
let lgu = $('#prodLgu').val();
// 파일 label 이름 변경
$('#uploadFile').on('change', function() {
console.log($('#uploadFile').get(0).files);
// 선택된 파일이 있는지 확인
if ($('#uploadFile').get(0).files.length > 0) {
// 파일 이름을 레이블에 설정
$('#fileLabel').text($('#uploadFile').get(0).files[0].name);
} else {
// 파일이 선택되지 않았을 경우 기본 텍스트로 설정
$('#fileLabel').text('파일을 선택해주세요');
}
});
})
</script>
JAVA
ProdVO.java
삭제 여부 추가
package kr.or.ddit.vo;
import java.util.Date;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import lombok.Data;
@Data
public class ProdVO {
private int rnum;
private String prodId;
private String prodName;
private String prodLgu;
private String prodBuyer;
private int prodCost;
private int prodPrice;
private int prodSale;
private String prodOu;
private String prodDetail;
private String prodImg;
private int prodTotalstock;
private Date prodInsdate;
private String prodOutline;
private int prodProperstock;
private String prodSize;
private String prodColor;
private String prodDelivery;
private String prodUnit;
private int prodQtyin;
private int prodQtysale;
private int prodMileage;
private long fileGroupNo;
private String prodDelYn;
private MultipartFile[] uploadFile;
private List<CartVO> cartVoList;
private FileGroupVO fgvo;
}
ProdController.java
package kr.or.ddit.controller;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import kr.or.ddit.service.ProdService;
import kr.or.ddit.util.ArticlePage;
import kr.or.ddit.util.UploadController;
import kr.or.ddit.vo.BuyerVO;
import kr.or.ddit.vo.LprodVO;
import kr.or.ddit.vo.MemberVO;
import kr.or.ddit.vo.ProdVO;
import kr.or.ddit.vo.TblUserVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequestMapping("/prod")
@Controller
public class ProdController {
@Autowired
ProdService service;
@ModelAttribute
public void prodInit(Model model) {
model.addAttribute("title", "상품 정보");
}
@GetMapping("/list")
public String list(Model model, @RequestParam(value="currentPage", required = false, defaultValue = "1") int currentPage) {
Map<String, Object> map = new HashMap<>();
int size = 10;
int total = this.service.getTotal();
map.put("currentPage", currentPage);
map.put("size", size);
List<ProdVO> list = this.service.list(map);
map.clear();
// model.addAttribute("data", list);
model.addAttribute("data", new ArticlePage<ProdVO>(total, currentPage, size, list, map));
return "prod/list";
}
@ResponseBody
@PostMapping("/listAjax")
public List<ProdVO> listAjax(@RequestBody ProdVO vo){
List<ProdVO> list = this.service.cartlist(vo);
return list;
}
@ResponseBody
@PostMapping("/memInfo")
public MemberVO memDetail(@RequestBody MemberVO vo) {
vo = this.service.memDetail(vo);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String datestr = sdf.format(vo.getMemBir());
vo.setMemBirStr(datestr);
return vo;
}
@GetMapping("/cart")
public String cart(Model model) {
return "prod/cart";
}
@ResponseBody
@GetMapping("/prodlist")
public ArticlePage<ProdVO> prodList(Model model, @RequestParam(value="currentPage", required = false, defaultValue = "1") int currentPage) {
Map<String, Object> map = new HashMap<>();
int size = 10;
int total = this.service.getTotal();
map.put("currentPage", currentPage);
map.put("size", size);
List<ProdVO> list = this.service.list(map);
map.clear();
ArticlePage<ProdVO> art = new ArticlePage<ProdVO>(total, currentPage, size, list, map);
return art;
}
@GetMapping("/cardForm")
public String cardForm(Model model) {
// 카드번호 자동 생성
List<String> cardRndNo = new ArrayList<String>();
for(int i=0; i<3; i++) {
Random rand = new Random();
cardRndNo.add(""+rand.nextInt(1000000000));
}
model.addAttribute("cardList", cardRndNo);
return "prod/cardForm";
}
@ResponseBody
@PostMapping("/cardFormPost")
public TblUserVO cardFormPost (TblUserVO vo) {
log.info("vo "+vo);
int result = this.service.cardFormPost(vo);
log.info("result "+result);
return vo;
}
@GetMapping("/regist")
public String regist(Model model) {
List<LprodVO> lprod = this.service.lprodList();
model.addAttribute("lprod",lprod);
return "prod/regist";
}
@ResponseBody
@PostMapping("/buyer")
public List<BuyerVO> buyerList(@RequestBody BuyerVO vo) {
List<BuyerVO> buyer = this.service.buyerList(vo);
return buyer;
}
@ResponseBody
@PostMapping("/createProdId")
public String createProdId(@RequestBody ProdVO vo) {
log.info("vo >>"+vo);
String prodId = this.service.createProdId(vo);
log.info("id >>"+prodId);
return prodId;
}
@PostMapping("/registPost")
public String registPost(ProdVO prodVo) {
log.info("vo >>"+prodVo);
int result = this.service.registPost(prodVo);
log.info("result >> "+result);
// return "redirect: /prod/list";
return "redirect: /prod/detail?prodId="+prodVo.getProdId();
}
@GetMapping("/detail")
public String detail(@RequestParam("prodId") String prodId, Model model) {
ProdVO prodVo = new ProdVO();
prodVo.setProdId(prodId);
log.info("vo >>"+prodVo);
BuyerVO buyer = this.service.detail(prodVo);
log.info("vo >>"+buyer);
model.addAttribute("buyer", buyer);
return "prod/detail";
}
@GetMapping("/edit")
public String edit(@RequestParam("prodId") String prodId, Model model) {
ProdVO prodVo = new ProdVO();
prodVo.setProdId(prodId);
log.info("vo >>"+prodVo);
BuyerVO buyer = this.service.detail(prodVo);
log.info("vo >>"+buyer);
model.addAttribute("buyer", buyer);
List<LprodVO> lprod = this.service.lprodList();
List<BuyerVO> buySel = this.service.buyerList(buyer);
model.addAttribute("sel", buySel);
model.addAttribute("lprod", lprod);
return "prod/edit";
}
@PostMapping("/updatePost")
public String updatePost(ProdVO prodVo) {
log.info("vo >>"+prodVo);
int result = this.service.updatePost(prodVo);
log.info("result >> "+result);
return "redirect: /prod/detail?prodId="+prodVo.getProdId();
}
@GetMapping("delete")
public String delete(@RequestParam("prodId") String prodId) {
int result = this.service.delete(prodId);
log.info("result >> "+result);
return "redirect: /prod/list";
}
}
ProdService.java
package kr.or.ddit.service;
import java.util.List;
import java.util.Map;
import kr.or.ddit.vo.BuyerVO;
import kr.or.ddit.vo.LprodVO;
import kr.or.ddit.vo.MemberVO;
import kr.or.ddit.vo.ProdVO;
import kr.or.ddit.vo.TblUserVO;
public interface ProdService{
public List<ProdVO> list(Map<String, Object> map);
public int getTotal();
public List<ProdVO> cartlist(ProdVO vo);
public MemberVO memDetail(MemberVO vo);
public int cardFormPost(TblUserVO vo);
public List<LprodVO> lprodList();
public List<BuyerVO> buyerList(BuyerVO bvo);
public String createProdId(ProdVO vo);
public int registPost(ProdVO vo);
public BuyerVO detail(ProdVO prodVo);
public int updatePost(ProdVO prodVo);
public int delete(String prodId);
}
ProdServiceImpl.java
package kr.or.ddit.service.impl;
import java.io.File;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import kr.or.ddit.dao.ProdDao;
import kr.or.ddit.mapper.FileGroupMapper;
import kr.or.ddit.mapper.ProdMapper;
import kr.or.ddit.service.ProdService;
import kr.or.ddit.util.UploadController;
import kr.or.ddit.vo.BuyerVO;
import kr.or.ddit.vo.CardVO;
import kr.or.ddit.vo.CarsVO;
import kr.or.ddit.vo.FileDetailVO;
import kr.or.ddit.vo.FileGroupVO;
import kr.or.ddit.vo.LprodVO;
import kr.or.ddit.vo.MemberVO;
import kr.or.ddit.vo.ProdVO;
import kr.or.ddit.vo.TblHobbyVO;
import kr.or.ddit.vo.TblUserVO;
@Service
public class ProdServiceImpl implements ProdService{
@Autowired
ProdMapper mapper;
@Autowired
String uploadPath;
@Autowired
FileGroupMapper fileMapper;
@Autowired
UploadController upload;
@Override
public List<ProdVO> list(Map<String,Object> map) {
return this.mapper.prodList(map);
}
@Override
public int getTotal() {
return this.mapper.prodListTotal();
}
@Override
public List<ProdVO> cartlist(ProdVO vo) {
return this.mapper.cartlist(vo);
}
@Override
public MemberVO memDetail(MemberVO vo) {
return this.mapper.memDetail(vo);
}
@Override
public int cardFormPost(TblUserVO vo) {
// 1) tbl_user 테이블 insert
int result = this.mapper.insertTblUser(vo);
// 2) card 테이블에 insert
List<CardVO> cardvo = vo.getCardVoList();
String userId = vo.getUserId();
for(CardVO v : cardvo) {
v.setUserId(userId);
result+= this.mapper.insertCard(v);
}
// 3) hobby에 insert
List<TblHobbyVO> hobbyvo = new ArrayList<TblHobbyVO>();
String[] hobby = vo.getHobby(); // hobby 배열을 사용
// String[] hobby = vo.getHobbyStr().split(","); // hobbyStr을 활용
if(hobby!=null) {
for(String h: hobby) {
TblHobbyVO hvo = new TblHobbyVO();
hvo.setUserId(userId);
hvo.setHobby(h);
hobbyvo.add(hvo);
result+= this.mapper.insertHobby(hvo);
}
}
// 4) cars에 insert
List<CarsVO> carsVoList = new ArrayList<CarsVO>();
String[] cars = vo.getCars();
for(String car: cars) {
CarsVO cvo = new CarsVO();
cvo.setUserId(userId);
cvo.setCar(car);
carsVoList.add(cvo);
}
result+=this.mapper.insertCars(carsVoList);
return result;
}
@Override
public List<LprodVO> lprodList() {
return this.mapper.lprodList();
}
@Override
public List<BuyerVO> buyerList(BuyerVO bvo) {
return this.mapper.buyerList(bvo);
}
@Override
public String createProdId(ProdVO vo) {
return this.mapper.createProdId(vo);
}
@Override
public int registPost(ProdVO vo) {
long groupNo = upload.multiImageUpload(vo.getUploadFile());
vo.setFileGroupNo(groupNo);
return this.mapper.registPost(vo);
}
// 연 / 월 / 일 폴더 생성
public String getFolder() {
// 2024-08-06 형식(format)지정
// 간단한 날짜 형식
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date today = new Date();
String str = sdf.format(today);
// 2024-08-06 > 2024\\08\\06
return str.replace("-", File.separator);
}
@Override
public BuyerVO detail(ProdVO prodVo) {
return this.mapper.detail(prodVo);
}
@Override
public int updatePost(ProdVO prodVo) {
MultipartFile[] multipartFiles = prodVo.getUploadFile();
if(multipartFiles[0].getOriginalFilename().length()>0) {
ProdVO vo = this.mapper.fileInfo(prodVo);
int result = 0;
long fileGroupNo = this.upload.multiImageUpload(multipartFiles);
prodVo.setFileGroupNo(fileGroupNo);
if(vo!=null) {
FileGroupVO fg = vo.getFgvo();
result = this.mapper.updatePost(prodVo);
result = this.upload.deleteFile(fg);
}else {
result = this.mapper.updatePost(prodVo);
}
return result;
} else {
return this.mapper.updatePost(prodVo);
}
}
@Override
public int delete(String prodId) {
ProdVO prodVo = new ProdVO();
prodVo.setProdId(prodId);
ProdVO vo = this.mapper.fileInfo(prodVo);
FileGroupVO fg = vo.getFgvo();
int result = this.mapper.delete(prodId);
result += this.upload.deleteFile(fg);
return result;
}
}
ProdMapper.java
package kr.or.ddit.mapper;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Mapper;
import kr.or.ddit.vo.BuyerVO;
import kr.or.ddit.vo.CardVO;
import kr.or.ddit.vo.CarsVO;
import kr.or.ddit.vo.LprodVO;
import kr.or.ddit.vo.MemberVO;
import kr.or.ddit.vo.ProdVO;
import kr.or.ddit.vo.TblHobbyVO;
import kr.or.ddit.vo.TblUserVO;
@Mapper
public interface ProdMapper {
public List<ProdVO> prodList(Map<String, Object> map);
public int prodListTotal();
public List<ProdVO> cartlist(ProdVO vo);
public MemberVO memDetail(MemberVO vo);
public int insertTblUser(TblUserVO vo);
public int insertCard(CardVO v);
public int insertHobby(TblHobbyVO hvo);
public int insertCars(List<CarsVO> carsVoList);
public List<LprodVO> lprodList();
public List<BuyerVO> buyerList(BuyerVO bvo);
public String createProdId(ProdVO vo);
public int registPost(ProdVO vo);
public BuyerVO detail(ProdVO vo);
public int updatePost(ProdVO prodVo);
public int delete(String prodId);
public ProdVO fileInfo(ProdVO pvo);
}
UploadController.java
package kr.or.ddit.util;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.multipart.MultipartFile;
import kr.or.ddit.mapper.FileGroupMapper;
import kr.or.ddit.vo.FileDetailVO;
import kr.or.ddit.vo.FileGroupVO;
import lombok.extern.slf4j.Slf4j;
//자바빈 객체로 등록
@Slf4j
@Controller
public class UploadController {
//DI, IoC
//root-context.xml에 <bean.. 으로 존재함
@Autowired
String uploadPath;
@Autowired
FileGroupMapper fileGroupMapper;
/**다중 이미지 업로드
* return : 20240808001(FILE_GROUP.FILE_GROUP_NO)
*/
public long multiImageUpload(MultipartFile[] multipartFiles) {
long fileGroupNo = 0L;
int result = 0;
int counter = 1;//FILE_SN 컬럼을 위함(20240808001의1)(20240808001의2)
//연월일 폴더 설정
// C:\\upload
// + "\\" +
// 2024\\08\\08
File uploadPath = new File(this.uploadPath, this.getFolder());
if(uploadPath.exists()==false) {
uploadPath.mkdirs();
}
//원본 파일명
String fileName = "";
//MIME(Multipurpost Internet Mail Extension) 타입
String contentType = "";
//파일 크기
long fileSize = 0L;
//1) FILE_GROUP 테이블에 insert
FileGroupVO fileGroupVO = new FileGroupVO();
result += this.fileGroupMapper.insertFileGroup(fileGroupVO);
//향상된 for문
for(MultipartFile multipartFile : multipartFiles) {
fileName = multipartFile.getOriginalFilename();
contentType = multipartFile.getContentType();
fileSize = multipartFile.getSize();
UUID uuid = UUID.randomUUID();
fileName = uuid.toString() + "_" + fileName;
//File객체 설계(복사할 대상 경로, 파일명)
// C:\\upload\\2024\\08\\08 + "\\" + asdfasdf_개똥이.jpg
File saveFile = new File(uploadPath,fileName);
try {
//파일 복사 실행
//파일객체.transferTo(설계)
multipartFile.transferTo(saveFile);
//실행전 {fileGroupNo=0,fileRegdate=null}
//실행후 {fileGroupNo=20240808001,fileRegdate=null}
//2) FILE_DETAIL 테이블에 insert
FileDetailVO fileDetailVO = new FileDetailVO();
fileDetailVO.setFileSn(counter++);
fileDetailVO.setFileGroupNo(fileGroupVO.getFileGroupNo());
fileDetailVO.setFileOriginalName(multipartFile.getOriginalFilename());
fileDetailVO.setFileSaveName(fileName);//uuid + 파일명
// /upload/ == C:\\upload\\ + 2024\\08\\08 + "\\" + asdfasdf_파일명.jpg
fileDetailVO.setFileSaveLocate("/upload/" +
this.getFolder().replace("\\", "/") +
"/" + fileName
);
fileDetailVO.setFileSize(fileSize);
fileDetailVO.setFileExt(
fileName.substring(fileName.lastIndexOf(".")+1));//asdfasdf_파일명.jpg
fileDetailVO.setFileMime(contentType);
fileDetailVO.setFileFancysize(
makeFancySize(String.valueOf(fileSize))
);//bytes -> MB
fileDetailVO.setFileSaveDate(null);
fileDetailVO.setFileDowncount(0);
result += this.fileGroupMapper.insertFileDetail(fileDetailVO);
fileGroupNo = fileGroupVO.getFileGroupNo();
} catch (IllegalStateException | IOException e) {
log.error(e.getMessage());
}
}
log.info("result : " + result);
return fileGroupNo;
}
//연/월/일 폴더 생성
public String getFolder() {
//2022-11-16 형식(format) 지정
//간단한 날짜 형식
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//날짜 객체 생성(java.util 패키지)
Date date = new Date();
//2022-11-16
String str = sdf.format(date);
//2024-01-30 -> 2024\\01\\30
return str.replace("-", File.separator);
}
//이미지인지 판단. 썸네일은 이미지만 가능하므로..
public boolean checkImageType(File file) {
//MIME(Multipurpose Internet Mail Extensions) : 문서, 파일 또는 바이트 집합의 성격과 형식. 표준화
//MIME 타입 알아냄. .jpeg / .jpg의 MIME타입 : image/jpeg
String contentType;
try {
contentType = Files.probeContentType(file.toPath());
log.info("contentType : " + contentType);
//image/jpeg는 image로 시작함->true
return contentType.startsWith("image");
} catch (IOException e) {
e.printStackTrace();
}
//이 파일이 이미지가 아닐 경우
return false;
}
//fancySize 리턴("1059000")
public String makeFancySize(String bytes) {
log.info("bytes : " + bytes);
String retFormat = "0";
//숫자형문자->실수형으로 형변환(1059000)
Double size = Double.parseDouble(bytes);
String[] s = { "bytes", "KB", "MB", "GB", "TB", "PB" };
if (bytes != "0") {
//bytes->KB
int idx = (int) Math.floor(Math.log(size) / Math.log(1024));
DecimalFormat df = new DecimalFormat("#,###.##");
double ret = ((size / Math.pow(1024, Math.floor(idx))));
retFormat = df.format(ret) + " " + s[idx];
} else {
retFormat += " " + s[0];
}
return retFormat;
}
public int deleteFile(FileGroupVO fgvo) {
int result = 0;
// 파일 삭제
List<FileDetailVO> list = fgvo.getFileDetailVoList();
for(FileDetailVO fd : list) {
String path = "C:"+fd.getFileSaveLocate().replace("/", "\\");
File file = new File(path);
file.delete();
}
// 파일 detail 삭제
result=this.fileGroupMapper.fileDetailDelete(fgvo);
// 파일 group 삭제
result=this.fileGroupMapper.fileGroupDelete(fgvo);
return result;
};
}
FileGroupMapper.java
package kr.or.ddit.mapper;
import org.apache.ibatis.annotations.Mapper;
import kr.or.ddit.vo.FileDetailVO;
import kr.or.ddit.vo.FileGroupVO;
@Mapper
public interface FileGroupMapper {
public int insertFileGroup(FileGroupVO fgvo);
public int insertFileDetail(FileDetailVO fdvo);
public int fileGroupDelete(FileGroupVO fgvo);
public int fileDetailDelete(FileGroupVO fgvo);
}
Mybatis
prod_SQL.xml
기존에 prodList를 출력한 형식을
삭제인 것을 포함시키지 않게 조회하는 줄도 추가한 형태
<?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="kr.or.ddit.mapper.ProdMapper">
<resultMap type="buyerVo" id="buyerMap">
<result property="buyerId" column="BUYER_ID"/>
<result property="buyerName" column="BUYER_NAME"/>
<result property="buyerLgu" column="BUYER_LGU"/>
<result property="buyerBank" column="BUYER_BANK"/>
<result property="buyerBankno" column="BUYER_BANKNO"/>
<result property="buyerBankname" column="BUYER_BANKNAME"/>
<result property="buyerZip" column="BUYER_ZIP"/>
<result property="buyerAdd1" column="BUYER_ADD1"/>
<result property="buyerAdd2" column="BUYER_ADD2"/>
<result property="buyerComtel" column="BUYER_COMTEL"/>
<result property="buyerFax" column="BUYER_FAX"/>
<result property="buyerMail" column="BUYER_MAIL"/>
<result property="buyerCharger" column="BUYER_CHARGER"/>
<result property="buyerTelext" column="BUYER_TELEXT"/>
<collection property="prodVoList" resultMap="prodMap"></collection>
</resultMap>
<resultMap type="prodVo" id="prodMap">
<result property="rnum" column="RNUM"/>
<result property="prodId" column="PROD_ID"/>
<result property="prodName" column="PROD_NAME"/>
<result property="prodLgu" column="PROD_LGU"/>
<result property="prodBuyer" column="PROD_BUYER"/>
<result property="prodCost" column="PROD_COST"/>
<result property="prodPrice" column="PROD_PRICE"/>
<result property="prodSale" column="PROD_SALE"/>
<result property="prodOutline" column="PROD_OUTLINE"/>
<result property="prodDetail" column="PROD_DETAIL" jdbcType="CLOB" javaType="java.lang.String"/>
<result property="prodImg" column="PROD_IMG"/>
<result property="prodTotalstock" column="PROD_TOTALSTOCK"/>
<result property="prodInsdate" column="PROD_INSDATE"/>
<result property="prodProperstock" column="PROD_PROPERSTOCK"/>
<result property="prodSize" column="PROD_SIZE"/>
<result property="prodColor" column="PROD_COLOR"/>
<result property="prodDelivery" column="PROD_DELIVERY"/>
<result property="prodUnit" column="PROD_UNIT"/>
<result property="prodQtyin" column="PROD_QTYIN"/>
<result property="prodQtysale" column="PROD_QTYSALE"/>
<result property="prodMileage" column="PROD_MILEAGE"/>
<association property="fgvo" resultMap="fileGroupMap"/>
<collection property="cartVoList" resultMap="cartMap"/>
</resultMap>
<resultMap type="fileGroupVo" id="fileGroupMap">
<result property="fileGroupNo" column="FILE_GROUP_NO"/>
<result property="fileRegdate" column="FILE_REGDATE"/>
<association property="fileDetailVoList" resultMap="fileDetailMap"></association>
</resultMap>
<resultMap type="fileDetailVo" id="fileDetailMap">
<result property="fileSn" column="FILE_SN"/>
<result property="fileGroupNo" column="FILE_GROUP_NO"/>
<result property="fileOriginalName" column="FILE_ORIGINAL_NAME"/>
<result property="fileSaveName" column="FILE_SAVE_NAME"/>
<result property="fileSaveLocate" column="FILE_SAVE_LOCATE"/>
<result property="fileSize" column="FILE_SIZE"/>
<result property="fileExt" column="FILE_EXT"/>
<result property="fileMime" column="FILE_MIME"/>
<result property="fileFancysize" column="FILE_FANCYSIZE"/>
<result property="fileSaveDate" column="FILE_SAVE_DATE"/>
<result property="fileDowncount" column="FILE_DOWNCOUNT"/>
</resultMap>
<resultMap type="cartVo" id="cartMap">
<result property="cartProd" column="CART_PROD"/>
<result property="cartQty" column="CART_QTY"/>
<result property="cartMember" column="CART_MEMBER"/>
<result property="cartNo" column="CART_NO"/>
<collection property="memVo" resultMap="memMap"></collection>
</resultMap>
<resultMap type="memVo" id="memMap">
<result property="memId" column="MEM_ID"/>
<result property="memPass" column="MEM_PASS"/>
<result property="memName" column="MEM_NAME"/>
<result property="memRegno1" column="MEM_REGNO1"/>
<result property="memRegno2" column="MEM_REGNO2"/>
<result property="memBir" column="MEM_BIR"/>
<result property="memZip" column="MEM_ZIP"/>
<result property="memAdd1" column="MEM_ADD1"/>
<result property="memAdd2" column="MEM_ADD2"/>
<result property="memHometel" column="MEM_HOMETEL"/>
<result property="memComtel" column="MEM_COMTEL"/>
<result property="memHp" column="MEM_HP"/>
<result property="memMail" column="MEM_MAIL"/>
<result property="memJob" column="MEM_JOB"/>
<result property="memLike" column="MEM_LIKE"/>
<result property="memMemorial" column="MEM_MEMORIAL"/>
<result property="memMemorialday" column="MEM_MEMORIALDAY"/>
<result property="memMileage" column="MEM_MILEAGE"/>
<result property="memDelete" column="MEM_DELETE"/>
</resultMap>
<select id="prodList" resultMap="buyerMap" parameterType="hashMap">
WITH t AS (
SELECT
ROW_NUMBER() OVER (ORDER BY a.prod_id) AS rnum,
A.PROD_ID,
A.PROD_NAME,
A.PROD_BUYER,
A.PROD_SALE,
A.PROD_OUTLINE,
A.PROD_DETAIL,
B.BUYER_ID,
B.BUYER_NAME
FROM
BUYER B
JOIN PROD A ON B.BUYER_ID = A.PROD_BUYER
WHERE
NOT EXISTS (SELECT PROD_ID FROM PROD WHERE A.PROD_DEL_YN = 'Y')
)
SELECT
t.*
FROM
t
WHERE
t.rnum BETWEEN ((#{currentPage} - 1) * #{size}) + 1 AND #{currentPage} * #{size}
</select>
<select id="prodListTotal" resultType="int">
SELECT count(*)
FROM BUYER B, PROD A
WHERE B.BUYER_ID = A.PROD_BUYER
AND
NOT EXISTS (SELECT PROD_ID FROM PROD WHERE A.PROD_DEL_YN = 'Y')
</select>
<select id="cartlist" resultMap="prodMap" parameterType="prodVo">
select
c.cart_no, c.cart_prod, p.prod_name, c.cart_qty, p.prod_sale, c.cart_member, m.mem_name
from prod p
inner join cart c on c.cart_prod=p.prod_id
inner join member m on c.cart_member = m.mem_id
where c.cart_prod = #{prodId}
</select>
<select id="memDetail" parameterType="memVo" resultType="memVo">
select *
from member
where mem_id=#{memId}
</select>
<insert id="insertTblUser" parameterType="tblUserVo">
insert into tbl_user(USER_ID,PASSWORD,NAME,EMAIL,BIR,ZIPCODE,ADDR,ADDRDET)
values(#{userId},#{password},#{name},#{email},#{bir},#{zipcode},#{addr},#{addrdet})
</insert>
<insert id="insertCard" parameterType="cardVo">
insert into card(CARD_NO,CARD_YM,USER_ID)
values(#{cardNo},#{cardYm},#{userId})
</insert>
<insert id="insertHobby" parameterType="tblHobbyVo">
insert into tbl_hobby(user_id, hobby)
values(#{userId}, #{hobby})
</insert>
<!-- <insert id="insertCars" parameterType="carsVo"> -->
<!-- INSERT ALL -->
<!-- <foreach collection="list" item="item"> -->
<!-- INTO cars(user_id, car) VALUES (#{item.userId}, #{item.car}) -->
<!-- </foreach> -->
<!-- SELECT * FROM dual -->
<!-- </insert> -->
<update id="insertCars" parameterType="java.util.List">
<foreach collection="list" item="item" open="INSERT ALL" close="SELECT * FROM DUAL" separator=" " index="idx">
INTO cars(user_id, car) VALUES (#{item.userId}, #{item.car})
</foreach>
</update>
<select id="lprodList" resultType="LprodVo">
select *
from lprod
</select>
<select id="buyerList" resultType="buyerVo" parameterType="buyerVo">
select *
from buyer
where buyer_lgu=#{buyerLgu}
</select>
<select id="createProdId" parameterType="prodVo" resultType="String">
select 'P'||(substr(nvl(max(prod_id),#{prodLgu}||'000000'),2)+1)
from prod
where prod_lgu=#{prodLgu}
</select>
<insert id="registPost" parameterType="prodVo">
insert into prod(prod_id,prod_name,prod_lgu,prod_buyer,prod_sale,file_group_no
<if test="prodDetail!=null">,prod_detail</if>
)
values(#{prodId},#{prodName},#{prodLgu},#{prodBuyer},#{prodSale},#{fileGroupNo}
<if test="prodDetail!=null">,#{prodDetail}</if>
)
</insert>
<select id="detail" parameterType="prodVo" resultMap="buyerMap">
select *
from prod a
inner join buyer d on d.buyer_id=a.prod_buyer
left outer join file_group b on a.file_group_no=b.file_group_no
left outer join file_detail c on b.file_group_no=c.file_group_no
where a.prod_id=#{prodId}
</select>
<update id="updatePost" parameterType="prodVo">
update prod
set prod_name=#{prodName},
prod_buyer=#{prodBuyer},
prod_sale=#{prodSale},
prod_detail=#{prodDetail}
<if test="fileGroupNo!=null">
,file_group_no=#{fileGroupNo}
</if>
where prod_id = #{prodId}
</update>
<select id="fileInfo" parameterType="prodVo" resultMap="prodMap">
select *
from prod a, file_group b, file_detail c
where a.file_group_no=b.file_group_no
and b.file_group_no=c.file_group_no
and a.prod_id=#{prodId}
</select>
<update id="delete" parameterType="String">
update prod
set prod_del_yn = 'Y',
file_group_no = null
where prod_id=#{prod_id}
</update>
</mapper>
fileGroup_SQL.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="kr.or.ddit.mapper.FileGroupMapper">
<!-- file_group insert -->
<insert id="insertFileGroup" parameterType="fileGroupVo">
<!-- 숫자형 문자 + 숫자 => 숫자 -->
<selectKey order="BEFORE" keyProperty="fileGroupNo" resultType="long">
select nvl(max(file_group_no),to_char(sysdate,'YYYYMMDD')||'000')+1 file_group_no
from file_group
where to_char(sysdate,'YYYYMMDD') = to_char(file_regdate,'YYYYMMDD')
</selectKey>
insert into file_group(file_group_no, file_regdate)
values(#{fileGroupNo}, sysdate)
</insert>
<insert id="insertFileDetail" parameterType="fileDetailVo">
insert into file_detail(file_sn,file_group_no,file_original_name,
file_save_name,file_save_locate,file_size,file_ext,
file_mime,file_fancysize,file_save_date,file_downcount)
values(#{fileSn},#{fileGroupNo},#{fileOriginalName},#{fileSaveName},
#{fileSaveLocate},#{fileSize},#{fileExt},#{fileMime},#{fileFancysize},
sysdate, #{fileDowncount})
</insert>
<delete id="fileGroupDelete" parameterType="fileGroupVo">
delete from file_group
where file_group_no=#{fileGroupNo}
</delete>
<delete id="fileDetailDelete" parameterType="fileGroupVo">
delete from file_detail
where file_group_no=#{fileGroupNo}
</delete>
</mapper>
'Spring' 카테고리의 다른 글
[Spring] 입력값 검증 (Validator) (0) | 2024.08.09 |
---|---|
[Spring] 트랜잭션 관리 (0) | 2024.08.09 |
[Spring] 상품 상세 정보 (Detail) (0) | 2024.08.08 |
[Spring] 상품 추가에 상품 이미지 미리보기 (0) | 2024.08.08 |
[Spring] CKEditor5 (0) | 2024.08.08 |