아빠아버지
473
2019-05-15 23:14:18
2
113

디비에 있는 파일 값을 가져오는데 문제가 생기네요..ㅠㅠ


아래와 같이 filePath에서는 DB에 있는 첨부파일 정보를 가져오도록 했는데..

반복문을 돌릴 때 삭제할 파일의 갯수만큼 돌다보니..
filePath에 값을 가져올 때 java.lang.IndexOutOfBoundsException: Index: 7, Size: 3

이런 오류가 나 버리네요..ㅠㅠ 어찌보면 당연한데..

삭제를 해야 할 파일 정보를 가져올 때 어떤식으로 디비에서 가져와야 할까요??
가져와야 할 정보가 한 개일 수도 있고, 여러개일 수도 있는데...

//해당 Board_no에 맞는 첨부파일 목록을 가져온다.
List<FileDTO> fileView = boardDAO.fileView(dto.getBo_no());
//파일 경로 변수 초기화.
String filePath = "";
//삭제할 파일이 있을 경우.
if(file_old_no.get(0) != 0) {
	for(int i = 0; i < file_old_no.size(); i++) {
		System.out.println("삭제할 파일이 있습니다.");
		//boardDAO.fileUpdate(dto.getBo_no(), file_old_no.get(i));
		System.out.println("file_old_no : " + file_old_no.get(i));
		System.out.println("file_no : " + fileView.get(file_old_no.get(i)-1));
		
		filePath = fileView.get(file_old_no.get(i)-1).getFile_path() + "/" + fileView.get(file_old_no.get(i)-1).getFile_origin_name();
		System.out.println("filePath : " + filePath);
		File delFile = new File(filePath);
		//첨부파일 삭제
		if(delFile.exists()) {
		//		delFile.delete();
		}
	}





0
0
  • 답변 2

  • 코딩하는그리즈만
    50
    2019-05-15 23:31:17

    저라면 

    1. 삭제할 리스트를 먼저가지고 와서  for문을 돌립니다


    2. 해당 파일이 있는지 if(file.isFile()) 확인


    3. if에 해당해면 해당 파일을 삭제 file.delete();


    아니면   file_old_no 와 fileView 를 이중 for문으로 돌려서 처리할거같네요.


    도움이 되었으면 좋겠네요


    0
  • zepinos
    18k
    2019-05-15 23:40:35 작성 2019-05-15 23:49:54 수정됨

    먼저 웹페이지에서 기존 첨부된 파일을 삭제하면 javascript 의 변수에 해당 파일의 번호(이하 seq)를 배열 등으로 저장하세요. 그리고 새로 첨부되는 파일은 그냥 input 으로 등록해놓구요.

    그리고 submit 할 때 저장해둔 파일의 번호를 숨겨진 input 에 콤마로 구분해서 하나의 변수로 보내면 Spring 에서 해당 변수의 값을 콤마 기준으로 나눠서 List 객체로 저장해주는 기능이 있을 겁니다.


    그렇게 해서 얻은 변수가 file_old_no 라는 객체라면, Controller 에서 default 로 0 을 넣는 것 자체가 무의미합니다. 위 코드의 if 문에서 if (file_old_no != null && file_old_no.size() > 0) { 와 같이 하면 문제가 없을테니까요.

    그리고, 최적화는 나중에 생각하고, 일단 file_old_no 의 값을 꺼내서(예를 들면 2 와 4 가 들어있다면) DB에 한 번씩 select 해서 파일 실제 경로를 얻고 파일을 실제 삭제하고 해당 레코드를 지우면 됩니다. 이 때 각각 2 와 4 라는 값을 이용해서 select 하고 delete 하면 되죠. 이렇게 각각 처리하는 이유는, 중간에 어떠한 이유로 실패할 경우 DB 트랜젝션을 전체적으로 잡아놓으면 파일만 삭제되고 레코드는 남아있는게 하나의 파일이 아니라 여러개가 될 수 있기 때문입니다.

    그리고, 지금 위에서 발생한다는 오류는 결국 List 에서 몇 번째 값을 가져오는 .get() 을 가지고 seq 값으로 조회하는게 아닌가 싶습니다. 먼저 올리신 글도 이것 때문에 착각하시는 것 같은데, list 의 순번과 DB 에서 부여한 seq 는 동일하게 생각하시면 안됩니다. DB 에서 미리 첨부파일 모두를 가져온 뒤 그 중 seq 와 일치하는 걸 가져오려면 list 개수만큼 for 로 반복을 하면서 .get(i) 로 레코드 정보를 가져와서 그 중 seq(번호)에 해당하는 변수의 값이 일치하는지 비교하는게 맞습니다. 위에서 최적화 무시하고 한 번씩 쿼리를 실행한다고 했는데, 이게 싫어서 in 으로 여러개를 한꺼번에 불러오거나 전체 첨부파일 레코드를 다 불러온 뒤 원하는 것만 추출하려면 loop 돌면서 일치하는 걸 찾거나, 한 줄로 짧게 lambda 써서 filter 로 찾아내는 식으로 구현해야 합니다.


    잘 시간만 아니라면 간단한 예제라도 보여드리면 좋겠는데...게시판 댓글로 알려드리기엔 내용이 좀...


    첨언하자면

    fileView.get(file_old_no.get(i)-1)

    이 부분이 제일 문제인데, 미리 fileView 로 List<FileDTO> 을 담아놓고 찾는 방식이 아니라, boardDAO.fileRecord(int file_no) 형태의 메서드를 만들어서 FileDTO 하나, 즉 file_no 에 해당하는 파일 하나의 정보만 가져오는 걸 만들어서 fileView.get() 대신에 사용하도록 수정하면 됩니다. 물론 for 로 반복될 때마다 쿼리가 한 번씩 실행되겠죠. 그러니 성능상 좋진 않습니다.

    또다른 방법은 fileView 을 이용해서 원하는 레코드를 찾기 위해 for 을 돌면서 찾거나 stream() 을 이용해 lambda 로 filter 처리를 하는 겁니다. filterView.stream().filter(s -> s.getFile_no() == file_old_no(i)) 이런 식으로 하는거죠. (결국 이 lambda 도 for 을 줄여주는 것 밖에 안됩니다)



    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.