JDBC
JDBC (Java DataBase Connectivity)
: 데이터베이스는 파일의 형태로 데이터를 효율적으로 저장하기 위한 프로그램
> Java Application에서 데이터베이스를 사용하기 위해 데이터베이스와 소통해야 하는데, 이걸 가능하게 하는 API
1. Gradle
1) Build
>> JDK (Java Development Kit) : Java 언어를 Java Bytecode로 변환하는 컴파일러(javac)
* High Level Language를 Low Level Language로 >> 컴파일(Compile)한다.
* 프로젝트 소스코드를 실행 가능한 프로그램으로 >> "빌드(Build)"한다.
2) Build Automation Tool
- Maven & Gradle
- Java 프로젝트를 빌드하는데 사용되는 대표적인 도구.
- 소스코드 컴파일, 단위 테스트, 버전관리, JAR 생성 (배포를 위해 Java Class를 부수 정보와 함께 압축하는 형태)...
3) Dependency Management
: 프레임워크나 라이브러리(의존성)을 사용한다.
- 다른 개발자가 이미 만들어 놓은 것을 활용하는 것
- 해당 라이브러리 코드도 우리가 가져와서 설정해야 하는데, Maven&Gradle은 인터넷에 연결되어 있으면 라이브러리를 자동으로 가져온다!
>> 어떻게 가져오냐면?
Maven Repository에서 ! 검색 후 복사/붙여넣기~
2. Statement & ResultSet
1) JDBC
: Java에서 직접적으로 사용하는 것은 JDBC API.
- 데이터베이스와 소통하기 위한 드라이버가 필요하다 >> 드라이버를 관리해주는 클래스가 DriverManager!
(* 드라이버란? : GPU 같은 하드웨어, 또는 Low-Level Software와 소통하기 위한 소프트웨어 부품)
2) DriverManager
: DriverManager를 이용해 데이터베이스에 접근하기 위한 연결 형성
- 먼저 어디에 있는 데이터베이스인지 작성한다. (= JDBC URL)
(url은 데이터베이스 properties에서 찾을 수 있다)
String connectionString = "jdbc:sqlite:db.sqlite";
- 이 문자열을 DriverManager.getConnection에 인자로 전달하면 데이터베이스와 연결된다.
String connectionString = "jdbc:sqlite:db.sqlite"; try (Connection connection = DriverManager.getConnection(connectionString)) { System.out.println("Connection Success!"); } catch (SQLException e) { System.out.println(e.getErrorCode()); System.out.println(e.getMessage()); throw new RuntimeException(e); }
cf) 이전 버전의 JDBC에서는 클래스를 따로 가져왔어야 하지만, 이제는 할필요가 없다.try { Class.forName("org.sqlite.JDBC"); } catch (ClassNotFoundException e) { throw new RuntimeException(e); }
3) Statement
: SQL을 전달하는데 사용할 수 있는 Statement
> DriverManager한테 받은 Connection 객체를 활용.
> execute() 메서드로 SQL 쿼리를 실행.
try (Connection connection = DriverManager.getConnection(connectionString)) {
System.out.println("connection success!!");
// 데이터베이스 연결 객체로부터 Statement 객체를 받는다.
Statement statement = connection.createStatement();
// execute를 이용해 간단한 SQL 문을 사용한다.
statement.execute("drop table if exists user;");
statement.execute("""
create table user(
id INTEGER primary key AUTOINCREMENT,
username TEXT,
password TEXT,
first_name TEXT,
last_name TEXT,
email TEXT
);
""");
// 서로 다른 사용자 계정 3개 입력
statement.execute("""
insert into user (username, password, first_name, last_name, email)
values ("kim", "kim", "ys", "kim", "s@naver.com"),
("kang", "kang", "ym", "kang", "y@naver.com"),
("jo","jo", "sh", "jo", "j@naver.com");
""");
} catch (SQLException e) {
System.out.println(e.getErrorCode());
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
> 한 execute() 메서드 안에는 하나의 SQL 쿼리만을 실행할 수 있다. (난 여러개 넣었다가 안됐다 ㅎㅎ.)
- executeQuery() : SELECT를 이용할 때 사용 >> ResultSet이 필요함.
- executeUpdate() : 데이터의 구조를 바꿀 때 사용 (update할때....) >> 내가 실행한 SQL문의 결과로 바뀐 줄의 갯수를 반환해줌.
- execute() : 결과를 정확히 알지 못할 때 대신 사용
String updateSql = """
update user
set first_name = 'Alexander'
where id = 1;
""";
int rows = statement.executeUpdate(updateSql);
System.out.println(rows);
4) ResultSet
- SELECT의 결과는 ResultSet 객체로 반환된다.
- next() : 결과 테이블의 다음 줄로/ 다음에 더이상 데이터가 없을 때 false 반환!
- get{type}() : type형으로 컬럼 데이터를 회수하기 위해 사용.
public class Main {
public static void main(String[] args) {
//1. 어떤 데이터베이스에 연결할지를 String으로 작성
String connectionString = "jdbc:sqlite:db.sqlite";
//2 . 해당 데이터베이스에 연결
try (Connection connection = DriverManager.getConnection(connectionString)) {
System.out.println("connection success!!");
// 3. 데이터베이스 연결 객체로부터 Statement 객체를 받는다.
Statement statement = connection.createStatement();
String selectSql = """
SELECT * FROM user;
""";
// 조회하는 쿼리는 ResultSet으로 데이터를 받는다.
// ResultSet은 결과 테이블을 살펴볼 수 잇게 도와주는 인터페이스
ResultSet resultSet = statement.executeQuery(selectSql);
while (resultSet.next()) {
System.out.println(resultSet.getString("username"));
System.out.println(resultSet.getString("first_name"));
System.out.println(resultSet.getString("email"));
}
} catch (SQLException e) {
System.out.println(e.getErrorCode());
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
}
}
3. PreparedStatement
1) SQL Injection
: 사용자가 입력하는 데이터를 바탕으로 조회를 하고 싶을 수 있다....
ex.
Scanner sc = new Scanner(System.in);
String input = sc.nextLine(); //사용자의 입력 받음.
String injectSql = "SELECT * FROM user WHERE id=";
injectSql += input;
injectSql += ";";
>> 근데 이 때 사용자가 1 OR 1=1;을 입력한다면?
결과 Sql은
SELECT * FROM user WHERE id = 1 OR 1=1;
>> 그럼 id값과 상관없이 모든 user의 정보가 노출되게 된다....!!!!! OMG
이게 SQL Injection..
** 매우 매우 위험한 행동이다!! 보안적으로 문제가 생김.**
2) PreparedStatement
: SQL 쿼리문에 빈칸을 만들어 값을 대입하여 사용할 수 있다.
- SQL문을 먼저 준비!!
- ?로 값을 넣을 곳 작성.
- set{Type} 메서드로 몇번째 빈칸에 어떤 데이터가 들어갈지 지정.
- 단, 테이블 이름은 변수로 사용 불가. (값만 넣을 수 있다!!)
// updateArticle
public boolean updateArticle(int id, String change, String changedInput) {
String targetSql = "UPDATE article SET "+change+" = ? WHERE id = ?;";
try (PreparedStatement statement = connection.prepareStatement(targetSql)) {
statement.setString(1, changedInput); //첫번째 물음표에 changedInput을 넣겠다.
statement.setInt(2, id); // 두번째 물음표에 id를 넣겠다.
statement.execute(); // PreparedStatement 실행
return true;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
'Programming > Database' 카테고리의 다른 글
Redis (1) | 2024.02.14 |
---|---|
Transaction (0) | 2024.02.02 |
정규화 Normalization와 조인 Join (1) | 2023.12.19 |
[연습문제 모음] (0) | 2023.12.18 |
Database 기초 (0) | 2023.12.18 |