JDBC
- 자바 어플리케이션이 관계형 데이터베이스와 연결할 수 있게 해주는 소프트웨어
![](https://velog.velcdn.com/images/onetuks/post/9a9e1566-7d6f-482c-89b3-d0a743fb3a5f/image.png)
JDBC Driver Model
- 4개의 타입
- MySQL에서는 type4(Thin Driver -Fully Java Driver) JDBC Driver 제공
JDBC Flow
![](https://velog.velcdn.com/images/onetuks/post/0c7673a3-9ae9-4b22-89df-dfe8b6ea8ef2/image.png)
- DriverManager 를 통해 커넥션 객체 받아옴
- Connection 통해 Statement 가져옴
- Statement 통해 쿼리 실행 → ResultSet 가져오거나 update 실행
- 데이터베이스 커넥션 종료 → 꼭 해줘야 함.
AutoClose
public static void main(String[] args) {
try (
var connection = DriverManager.getConnection("jdbc:mysql://localhost/order_mgmt", "root", "root1234!");
var statement = connection.createStatement();
var resultSet = statement.executeQuery("select * from customers");
) {
while (resultSet.next()) {
var name = resultSet.getString("name");
var customerId = UUID.nameUUIDFromBytes(resultSet.getBytes("customer_id"));
logger.info("customer Id -> {} name -> {}", customerId, name);
}
} catch (SQLException exception) {
logger.error("Got error while closing connection", exception);
}
}
PrepareStatement
- SQL 쿼리에 공격자가 임의의 sql을 삽입하는 공격,
sql injection
.
- 이를 방지하는 방법
- 미리 준비된 구문을 실행만 하기 때문에 보안, 성능에 강점
- 대신 autoclose 가 안 되기 때문에 try 블록으로 넣어줘야 함
public static void main(String[] args) {
try (
var connection = DriverManager.getConnection("jdbc:mysql://localhost/order_mgmt", "root", "root1234!");
var statement = connection.prepareStatement("select * from customers");
) {
statement.executeStatement();
try (var resultSet = statement.executeQuery()) {
while (resultSet.next()) {
var name = resultSet.getString("name");
var customerId = UUID.nameUUIDFromBytes(resultSet.getBytes("customer_id"));
logger.info("customer Id -> {} name -> {}", customerId, name);
}
}
} catch (SQLException exception) {
logger.error("Got error while closing connection", exception);
}
}
UUID 주의사항
var customerId = UUID.nameUUIDFromBytes(resultSet.getBytes("customer_id"));
- nameUUIDFromBytes 는 UUID 3버전의 메소드
- UUID.randomeUUID 는 4버전의 메소드
- 둘의 버전과 바이트 제한이 다르기 때문에 논리 오류가 발생
- insert로 만든 entity랑 find로 찾은 entity랑 id가 다른 현상
- UUID를 두 개의 바이트로 쪼개서 합치는 방식으로 해결
private UUID toUUID(byte[] customerIds) {
var byteBuffer = ByteBuffer.wrap(customerIds);
return new UUID(byteBuffer.getLong(), byteBuffer.getLong());
}
var customerId = toUUID(resultSet.getBytes("customer_id"));
SpringBoot #2.2 JDBC
JDBC
- 자바 어플리케이션이 관계형 데이터베이스와 연결할 수 있게 해주는 소프트웨어
![스크린샷 2023-06-27 오전 10.39.31.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6bc0d0d6-a471-4c91-8bc0-68e4cb384f47/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-06-27_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_10.39.31.png)
JDBC Driver Model
- 4개의 타입
- MySQL에서는 type4(Thin Driver -Fully Java Driver) JDBC Driver 제공
JDBC Flow
![스크린샷 2023-06-27 오전 10.41.26.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/174872e3-e0de-4520-a6f2-99b4e215d689/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-06-27_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_10.41.26.png)
- DriverManager 를 통해 커넥션 객체 받아옴
- Connection 통해 Statement 가져옴
- Statement 통해 쿼리 실행 → ResultSet 가져오거나 update 실행
- 데이터베이스 커넥션 종료 → 꼭 해줘야 함.
AutoClose
public static void main(String[] args) {
try (
var connection = DriverManager.getConnection("jdbc:mysql://localhost/order_mgmt", "root", "root1234!");
var statement = connection.createStatement();
var resultSet = statement.executeQuery("select * from customers");
) {
while (resultSet.next()) {
var name = resultSet.getString("name");
var customerId = UUID.nameUUIDFromBytes(resultSet.getBytes("customer_id"));
logger.info("customer Id -> {} name -> {}", customerId, name);
}
} catch (SQLException exception) {
logger.error("Got error while closing connection", exception);
}
}
PrepareStatement
- SQL 쿼리에 공격자가 임의의 sql을 삽입하는 공격,
sql injection
.
- 이를 방지하는 방법
- 미리 준비된 구문을 실행만 하기 때문에 보안, 성능에 강점
- 대신 autoclose 가 안 되기 때문에 try 블록으로 넣어줘야 함
public static void main(String[] args) {
try (
var connection = DriverManager.getConnection("jdbc:mysql://localhost/order_mgmt", "root", "root1234!");
var statement = connection.prepareStatement("select * from customers");
) {
statement.executeStatement();
try (var resultSet = statement.executeQuery()) {
while (resultSet.next()) {
var name = resultSet.getString("name");
var customerId = UUID.nameUUIDFromBytes(resultSet.getBytes("customer_id"));
logger.info("customer Id -> {} name -> {}", customerId, name);
}
}
} catch (SQLException exception) {
logger.error("Got error while closing connection", exception);
}
}
UUID 주의사항
var customerId = UUID.nameUUIDFromBytes(resultSet.getBytes("customer_id"));
- nameUUIDFromBytes 는 UUID 3버전의 메소드
- UUID.randomeUUID 는 4버전의 메소드
- 둘의 버전과 바이트 제한이 다르기 때문에 논리 오류가 발생
- insert로 만든 entity랑 find로 찾은 entity랑 id가 다른 현상
- UUID를 두 개의 바이트로 쪼개서 합치는 방식으로 해결
private UUID toUUID(byte[] customerIds) {
var byteBuffer = ByteBuffer.wrap(customerIds);
return new UUID(byteBuffer.getLong(), byteBuffer.getLong());
}
var customerId = toUUID(resultSet.getBytes("customer_id"));
DataAccessException
- JDBC 사용하면서 발생하는 예외에 대한 캡슐 클래스
- 데이터베이스 사용하면서 발생하는 모든 예외에 대해 catch가 가능하므로 하위 예외를 catch 문에서 잡아서 개별 처리 가능