본문 바로가기
개발 일기

2024-11-07 / PJ - 헤맸던 부분, Spirng - Item 정의, JAVA-Mysql 연결 및 쿼리

by 어떻게말이름이히힝 2024. 11. 7.
  • JavaScript 이벤트 처리 삭제 버튼의 클릭 이벤트
    $("#deleteBtn").click(async function () { console.log("삭제 동작 확인"); }); //콘솔에 로그가 출력되지 않음
    $(".dinner-getcontainer").on("click", ".delete-dinner", async function () {console.log("삭제 동작 확인"); });

    이벤트 위임방식 사용 : dinner-getcontainer는 부모 요소이며, 지정된 자식 요소 delete-dinner에서 click 발생 시 3번째에 있는 함수가 실행됨
    이벤트 버블링의 개념 : 자식 요소에서 발생한 이벤트는 상위로 전파됨

  • CSS 레이아웃 문제 버튼 위치 조정: float 기능을 사용하여 해결함. VC에서 alt+B를 누르면 바로 웹 페이지 실행되고 코드 바꾼 후 저장 -> 새로 고침하면 바로 바꾼게 보여서 지속적으로 조정함.

  • 두 개의 Firebase 앱 초기화: Firebase를 두 개 연결하는 과정에서 어려움이 있었습니다. 첫 번째 초기화 할 때는 [default]로 이름이 지정되지만, 두 번째 초기화할 때는 두 번째 인자에 이름 지정이 필요했고  initializeApp(firebaseConfig_fordinner, "secondary");로 두 번째 Firebase 연결에 성공했습니다.

  • FireStore Database 보안 규칙: 제3자가 Firebase Firestore Database에 접근하지 못하도록 하기 위해 보안 규칙을 설정하는 과정에서 문제가 있었습니다. if request.auth != null;로 설정하고 깃허브 도메인을 등록했으나 GitHub에 올린 페이지에서 데이터를 읽을 수 없었습니다. 

    + firebaseConfig를 담은 부분에서 projectId를 제외한 모든 필드를 주석 처리했는데도 데이터베이스에 접근이 가능했음. 어떻게 접근을 막을지? 
    - projectId : 프로젝트의 고유 식별자
    - apiKey : Firebase 서비스와 통신할 때 사용되는 인증 키
    - authDomain : 인증을 처리하는 도메인, 이 도메인을 사용해서 사용자 로그인, 회원가입 등 인증 작업을 처리할 수 있음
    - storageBucket : Firebase Storage에서 파일을 저장하는 버킷의 URL, 파일 업로드 및 다운로드 시 이 버킷 사용
    - messagingSenderId : 푸시 알림 전송에 사용됨
    - appId : 프로젝트 고유 앱 Id, 앱 데이터를 추적할때 필요
    내가 어떤 점을 모르는지, 어떤 점에서 막히는지 모르겠고 미해결 상태로 두고 좀 더 배우면 다시 보는 걸로 결정했다. 

 

 

csv 파일 : 데이터를 쉼표로 구분하여 저장하는 텍스트 파일 형식

Item : 처리하는 데이터의 가장 작은 단위, 데이터베이스 기준으로는 하나의 행(row)을 의미하며 파일 기준으로는 하아늬 record(파일의 한줄)을 의미

Spring 에서 Item 기반 배치처리

- ItemReader : 데이터를 읽어오는 역할, read() 메소드를 통해 하나의 Item 반환, 읽을 데이터가 없으면 NULL을 반환
- ItemProcessor : 읽어온 데이터를 가공하거나 필터링

- ItemWriter : 대량의 데이터를 한 번에 메모리에 모두 적재하지 않고 일정한 크기(chunk)로 나누어 처리 / "chunkSize = 10"으로 설정하면 한번에 10개의 Item을 처리함

 

(182p 공부 중, 해당 페이지에서 JDBC웹 프로그래밍을 먼저 공부하고 오라고 함)

 

Class.forName("com.mysql.jdbc.Driver"); 

클래스의 forName은 클래스를 로드하는 메소드, 여기선 JDBC 드라이버를 로드한다.(JDBC 드라이버가 없으면 ClassNotFoundException이 발생하므로 try/catch 문을 사용한다.)

여기 "com.mysql.jdbc.Driver" 부분은 사용하는 DBMS에 따라 달라질 수 있음

*오라클은 "oracle.jdbc.driver.OracleDriver", MS SQL은 "com.microsoft.sqlserver.jdbc.SQLServerDriver"

* 최신 버전 MySQL "com.mysql.cj.jdbc.Driver"로 변경

 

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost::3306/sampledb","root","");

: DriverManager.getConnection() 메소드는 Connection 객체를 반환 받는다.

- URL : "jdbc:mysql://localhost:3306/sampledb" 에서" jdbc:mysql://" 부분은 JDBC 드라이버를 통해 MySQL 데이터베이스에 연결한다는 것을 나타내며, "localhost"는 데이터베이스 서버의 주소, "3306"은 포트 번호이며 여기서는 MySQL이 사용하는 기본 포트여서 DBMS에 따라 달라질 수 있다. "sampledb"는 데이터베이스 이름이다.
- 사용자 이름 : "root" 
- 비밀번호 : ""

연결이 되지 않으면 SQLException이 발생함, try/catch를 통해 예외 처리를 꼭! 해주어야함

* 성능 향상을 위해 Connection 객체는 명시적으로 conn.close()를 통해 자원을 해제하거나 "AutoCloseable" 인터페이스를 구현하고 있어 try-with-resources 구문(Connection 객체가 파라미터로 들어가는 형식)안에 선언되면 try 블록이 종료될때 자동으로 conn.close()를 호출해준다.

 

이거 두개로 로컬에 있는 Mysql에 연결하려 했으나 "JDBC Driver not found" 가 발생했다.

import java.sql.*;

public class sqltest {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/study", "root", "dlagmlgus");
            System.out.println("Database connection established");
        } catch (ClassNotFoundException e){
            System.out.println("JDBC Driver not found");
        } catch (SQLException e){
            System.out.println("SQLException caught");
        }
    }
}

 

해당 사이트에서 Platform Independent 로 파일을 받는다.

MySQL :: Download Connector/J

 

MySQL :: Download Connector/J

MySQL Connector/J is the official JDBC driver for MySQL. MySQL Connector/J 8.0 and higher is compatible with all MySQL versions starting with MySQL 5.7. Additionally, MySQL Connector/J 8.0 and higher supports the new X DevAPI for development with MySQL Ser

dev.mysql.com

 

IntelliJ 기준 프로젝트 이름 우클릭 > "모듈 설정 열기"를 클릭

 

적용 > 확인

연결 된 것 확인.

 

자바에서 SQL 문을 실행하기 위해서는 Statement 클래스를 이용하고 SQL 문 실행 결과를 얻어오기 위해서는 ResultSet 클래스를 이용한다.

 

Statement 클래스 메소드

- ResultSet executeQuery(String sql) : 주어진 sql문을 실행하고 ResultSet 객체에 반환

- int executeUpdate(String sql) : INSERT, UPDATE 또는 DELETE과 같은 sql문을 실행하고 sql문 실행으로 영향을 받은 행의 개수나 0을 반환함

- void close() : 이것도 앞에 Connection 객체와 똑같이 close 해주어야하지만 try-with-resources 방식으로 자동으로 리소스를 닫을 수 있다.

 

ResultSet 클래스 메소드 //해당 객체는 현재 데이터의 행을 가리키는 커서(cursor)를 관리, 초기 값은 첫 번째 행 이전을 가리킴

- boolean first() : 커서를 첫 번째 행으로 이동

- boolean last() : 커서를 마지막 행으로 이동

- boolean next() : 커서를 다음 행으로 이동

- boolean previous() : 커서를 이전 행으로 이동

- boolean absolute(int row) : 커서를 지정된 행 row로 이동

- boolean isFirst() : 첫 번째 행이면 true 반환

- boolean isLast() : 마지막 행이면 true 반환

- void close() : Statement 클래스 메소드와 동일

- Xxx getXxx(String columnLable) : Xxx 는 데이터 타입을 나타내고, 현재 행에서 지정된 열 이름(columnLable)에 해당하는 데이터를 반환한다. int형 데이터를 읽는 메소드는 getInt()

- Xxx getXxx(int columnIndex) : 현재 행에서 지정된 열 인덱스에 해당하는 데이터를 반환

 

테이블의 모든 데이터 검색

내 데이터베이스에는 orders라는 테이블이 있어서 그걸 조회해보려고 한다.

 

Statement orders = con.createStatement();
            ResultSet rs = orders.executeQuery("select * from orders");
            while (rs.next()) {
                System.out.println(rs.getInt(1) + " " + rs.getString(2) + " " + rs.getString(3));
            }

 

order 테이블에 있던 값이 그대로 출력 되었다.

동일하게 쿼리는 executeQuery("sql문") 으로 하고 데이터의 변경(레코드 추가, 수정, 삭제)는 executeUpdate("sql문")으로 한다.