일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 자바스크립트심화
- CSS
- 머신러닝
- 개발일기
- 상속
- 혼공머신
- 중학수학
- 오블완
- 자바스크립트
- 연습문제
- 데이터분석
- 컴퓨터구조
- 딥러닝
- 정보처리기사실기
- 컴퓨터비전
- 문자와식
- 자바
- JDBC
- 티스토리챌린지
- SQL
- 파이썬
- c언어
- 정보처리기사필기
- html/css
- 디버깅
- JSP/Servlet
- 자바 실습
- 중학1-1
- JSP
- 데이터베이스
- Today
- Total
클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지
JDBC 프로그래밍 7 - 단원 마무리 및 도전 문제 풀기 1 : 데이터베이스로 사진 저장하고 추출하기 본문
다음으로는 단원 마무리를 하며 도전 문제를 하나 풀어보려고 한다.
단원 요약하기
데이터베이스로 사진 저장 및 추출하기
문제 풀기
1. 테이블 생성
images라는 테이블을 MySQL에서 생성하려면 아래 SQL 명령어를 실행하면 된다.
SQL 코드 설명
- ID : 자동 증가(AUTO_INCREMENT)로 설정하여, 이미지 삽입 시 고유한 값이 자동으로 지정된다. 별도로 관리할 필요 없다.
- FILENAME : 이미지 파일 이름을 저장하는 열
- FILE : 실제 이미지 데이터를 저장하는 MEDIUMBLOB 타입
2. 데이터베이스 확인
테이블이 제대로 생성되었는지 확인하려면 아래 명령어를 실행한다.
3. 데이터 삽입 테스트
테이블이 잘 생성되었으면, 이미지를 저장하는 Java 코드를 작성하기 전에 직접 SQL을 사용해 데이터 삽입 테스트를 해볼 수 있다.
SQL 코드 설명
- LOAD_FILE('/path/to/your/image.jpg') : 파일 경로에 있는 이미지를 읽어와 MEDIUMBLOB 열에 저장
- 예: '/Users/username/Desktop/test_image.jpg' 또는 'C:/images/test_image.jpg'
테스트 코드로 데이터가 잘 삽입되는 것을 확인했으니 이제 진짜 설정할 코드를 작성해 보겠다.
4. 이미지 삽입 테스트
이미지를 저장하려면 MySQL에서 아래와 같은 설정이 필요하다.
다운 받은 사진을 이처럼 폴더에 저장하고 이 코드를 실행한다.
이 설정이 없으면 LOAD_FILE 함수가 작동하지 않을 수 있다.
5. 자바 코드 만들고 실행하기
코드 실행 결과 몇 가지 오류가 있으므로 한번 수정해 보겠다.
6. 코드 수정하기
1. MySQL 드라이버 경고
Class.forName("com.mysql.jdbc.Driver");
- 이 경고는 지금까지 많이 수정하며 아는 내용이므로 넘어가겠다.
2. ResultSet 사용 경고
ResultSet 객체를 사용하는 코드에서 경고가 발생할 수 있다.
Blob b = viewRS.getBlob("FILE");
img = new ImageIcon(b.getBytes(1, (int) b.length()));
- getBytes()는 대량의 바이너리 데이터를 다룰 때 비효율적일 수 있다는 경고를 표시한다.
- 경고를 무시해도 실행에는 문제가 없지만, 대량의 데이터를 처리해야 한다면 효율적인 방식으로 데이터를 처리하는 것이 좋다. 여기서는 getBytes()를 사용해도 괜찮다.
3. numberOfRecord 초기화 관련
numberOfRecord = srs.getInt(1);
- numberOfRecord를 사용할 때 초기화되지 않았다는 경고가 발생할 수 있다.
해결 방법
- 초기 값 설정하기
private int numberOfRecord = 0;
또는, 생성자에서 기본값을 명시적으로 설정
numberOfRecord = (srs != null && srs.next()) ? srs.getInt(1) : 0;
4. 자원 해제 관련 경고
자원(Connection, PreparedStatement, ResultSet)을 닫지 않았을 때 경고가 발생할 수 있다.
- 모든 자원에 대해 finally 블록 또는 try-with-resources를 사용해 명시적으로 닫아야 한다
try (ResultSet srs = stmt.executeQuery("select count(*) from images")) {
if (srs.next()) {
numberOfRecord = srs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
5. Connection과 Statement 경고
conn과 stmt 필드가 클래스 수준에서 선언되었지만, 사용 후 명시적으로 닫지 않아서 경고가 발생할 수 있다.
- 클래스 필드가 아닌, 지역 변수로 선언하는 것이 더 안전하다.
- try-with-resources를 사용해 자동으로 자원을 닫도록 처리
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/photodb", "root", "1234");
Statement stmt = conn.createStatement()) {
ResultSet srs = stmt.executeQuery("select count(*) from images");
if (srs.next()) {
numberOfRecord = srs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
6. 파일 스트림 경고
FileInputStream을 사용하면서 자원을 닫지 않았을 때 발생할 수 있다.
해결 방법
- try-with-resources를 사용해 스트림을 자동으로 닫도록 처리
try (FileInputStream fin = new FileInputStream(file)) {
PreparedStatement pre = conn.prepareStatement("INSERT INTO images (ID, FILENAME, FILE) VALUES (?, ?, ?)");
pre.setInt(1, numberOfRecord++);
pre.setString(2, file.getName());
pre.setBinaryStream(3, fin, (int) file.length());
pre.executeUpdate();
pre.close();
} catch (Exception e) {
handleError(e.getMessage());
}
학습을 마치고
문제가 아직 해결되지 않았지만 끝까지 코드를 수정하며 반드시 해결해 보기로 했다. 이 문제를 2시간도 훨씬 넘게 푼 것 같다. 도전 문제가 너무나도 어렵다.
'프로그래밍 언어 > 자바' 카테고리의 다른 글
JDBC 프로그래밍 9 - 연습문제 이론편 문제 풀기 (1) | 2024.12.14 |
---|---|
JDBC 프로그래밍 8 - 단원 마무리 및 도전 문제 풀기 2 : 코드 수정 및 결과 학인하기 (0) | 2024.12.14 |
JDBC 프로그래밍 6 - 자바의 JDBC 프로그래밍 3 : 데이터 변경 (2) | 2024.12.14 |
JDBC 프로그래밍 5 - 자바의 JDBC 프로그래밍 2 : 데이터베이스 사용과 데이터 검색 (2) | 2024.12.14 |
JDBC 프로그래밍 4 - 자바의 JDBC 프로그래밍 1 : 데이터베이스 연결 설정 (0) | 2024.12.14 |