DB
-
커넥션 풀 및 데이터 소스2023.10.25
-
JDBC2023.10.25
-
MySQL) 프로시저를 사용하여 더미 데이터 만들기2023.05.04
Docker를 통해 Mysql 설치
Mac에 Docker 깔기
brew 를 통해 Docker 깔기
brew install --cask docker
그후 아래 명령어를 통해 잘깔렸는지 확인해보기
docker -v
Docker에 Mysql 깔기
docker의 이미지 저장소에서 MySQL의 Docker 이미지를 로컬 시스템으로 다운로드 하기
docker pull mysql //버전을 지정하고 싶다면 docker pull mysql:버전
다운받은 docker 이미지 확인하기
docker images
MySQL Docker 컨테이너 생성 및 실행하기
docker run --name <컨테이너명> -e MYSQL_ROOT_PASSWORD=<password> -d -p 3306:3306 mysql:latest
생성된 컨테이너 리스트 확인하기
docker ps -a
<이때 우리가 받은 Image를 기반으로 생성된 Container가 보이면 된다>
DBeaver2 에 연결시 오류 해결
이런식으로 연결을 했는데 계속해서 Public Key Retrieval is not allowed
오류가 발생했다.
이때 Driver properties 에 추가정보를 제시하면 되는데 Driver Properties에 들어가서
allowPublicKeyRetrieval = true
로 설정해주면 연결에 성공한다.
'DB' 카테고리의 다른 글
h2 DB 연결 방법 (1) | 2023.11.27 |
---|---|
트랜잭션(transaction) (1) | 2023.11.22 |
커넥션 풀 및 데이터 소스 (0) | 2023.10.25 |
JDBC (0) | 2023.10.25 |
MySQL) 프로시저를 사용하여 더미 데이터 만들기 (0) | 2023.05.04 |
h2 DB 연결 방법
H2 DB 사용 방법
1. H2 DB 다운로드
h2 해당 사이트에 접속후 Download
에 들어가 운영체제에 맞는 h2
DB 를 다운받아준다.
Spring 을 사용하면 굳이 h2 DB 를 다운받지 않고 의존성만 추가해주면 사용할수 있지만, 이렇게하면 서버를 키지 않았을때 console에 접속할수가 없어 h2 DB를 다운받아 진행했다.
2. h2 실행
다운받은 h2 파일 안 h2/bin
에 들어가면 h2.sh
라는 파일이 있는데 해당 파일을 통해 h2
서버를 실행할수 있다.
터미널을 통해 h2/bin
디렉토리로 이동후 h2.sh
를 실행해준다.
이때 해당 파일을 실행할 권한이 없을수 있는데, 아래와 같은 명령어를 통해 실행 권한을 추가하면 된다.
chmod +x h2.sh
실행을 완료했다면
위와같은 콘솔창이 뜨게된다.
3. DB 생성
그후 평소처럼 사용하려고 했는데 다음과 같은 오류가 발생했다.
Database "/Users/chanyounkim/test" not found, either pre-create it or allow
remote database creation (not recommended in secure environments)
찾아보니
내가 사용하는 h2 의 2.2.224
버전에서는 db를 자동생성하지 않는다. 구버전으로 다운그레이드 하면 자동생성을 해준다는데 일단은 2.2.224
에서 db 를 생성해 사용하기로 했고, db 생성 방법은 아래와 같다.
h2를 터미널을 통해 실행을 했다면 오른쪽 위에 h2 아이콘이 있을텐데, 아이콘 클릭후 create a new database
를 누르면 다음과 같은 창이 뜬다.
해당 이미지에 Database path
, Username
, password
를 원하는데로 입력하면 된다. 나는 home
directory 에 만들고 싶어 경로를 다음과 같이 설정했다. ~/testDB
그후 터미널을 통해 확인해보면
우리가 만들어준 testDB.mv.db
가 존재하는것을 확인할수 있다.
4. DB 접속
DB까지 만들었다면 해당 DB에 접속을 하면 된다.
JDBC URL
에 testDB.mv.db
가 있는 경로를 지정해주고 연결을 누르면 연결이 잘되는 것을 확인할 수 있다.
'DB' 카테고리의 다른 글
Docker를 통해 Mysql 설치 (1) | 2023.11.27 |
---|---|
트랜잭션(transaction) (1) | 2023.11.22 |
커넥션 풀 및 데이터 소스 (0) | 2023.10.25 |
JDBC (0) | 2023.10.25 |
MySQL) 프로시저를 사용하여 더미 데이터 만들기 (0) | 2023.05.04 |
트랜잭션(transaction)
트랜잭션
데이터를 저장할때 DB에 저장하는 가장큰 이유중 하나는 DB는 트랜잭션이라는 개념을 지원하기 때문이다.
- A 계좌에서 출금
- B 계좌에 입금
@Transactional
애너테이션이 붙은 메서드에서는 해당 메서드 내의 모든 작업이 하나의 데이터베이스 트랜잭션 내에서 실행된다. 즉 위 와같은 예시에서 A의 계좌에서 출금이 된후 B계좌에 입금이 되는 작업을 하나로 묶어 처리한다는 뜻이다. 이 이유는 데이터 베이스 작업을 atomic으로 만들기 위함이다.
이때 1번 작업은 성공했는데 2번 작업이 실패한다면 롤백(Rollback)을 하면되고 1,2번 작업이 모두 성공하면 DB에 정상 반영하는 커밋(Commit)을 하게된다.
ACID
원자성(Atomicity) : 트랜잭션 내에서 실행한 작업은 모두 성공하거나 모두 실패해야한다.
일관성(Consistenct): 모든 트랜잭션은 일관성 있는 DB상태를 유지해야한다.
격리성(Isolation): 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다.
지속성(Durability): 트랜잭션을 성공적으로 끝내면 그 결과가 항상 기록되어야 한다. 즉 중간에 문제가 발생하더라도 DB의 로그 등을 사용해 성공한 트랜잭션 내용을 복구해야 한다.
❗️격리성을 완전히 보장하려면 트랜잭션을 거의 순서대로 실행해야 한다. 이렇게 하면 동시 처리 성능이 매우 나빠진다. 따라서 이런 문제를 해결하기 위해 ANSI 표준은 트랜잭션의 격리 수준을 4단계로 나누어 정의하며 이 4단계중 한단계를 선택할수 있다.
트랜잭션 격리 수준 - Isolation level
READ UNCOMMITED(커밋되지 않은 읽기)
- 이 수준에서는 다른 트랜잭션에서 커밋되지 않은 변경사항(즉, 아직 확정되지 않은 변경사항)도 조회할 수 있다. 이를
Dirty Read
라고 한다. - ex) 트랜잭션 A가 데이터 X를 수정하고 아직 커밋하지 않았다. 트랜잭션 B는 이 수정된(하지만 아직 커밋되지 않은) 데이터 X를 조회할 수 있다.
- 이 수준에서는 다른 트랜잭션에서 커밋되지 않은 변경사항(즉, 아직 확정되지 않은 변경사항)도 조회할 수 있다. 이를
READ COMMITTED(커밋된 읽기)
- 이 수준에서는 오직 커밋된 변경사항만 조회할 수 있다. 즉, 다른 트랜잭션에서 커밋되지 않은 변경사항은 보이지 않는다.
- ex) 트랜잭션 A가 데이터 X를 수정하고 아직 커밋하지 않았다. 트랜잭션 B는 이전 커밋된 상태의 데이터 X를 조회한다. A가 커밋한 후에 B가 다시 조회하면 변경된 X를 볼 수 있다.
REPEATABLE READ(반복 가능한 읽기)
- 이 수준에서는 트랜잭션이 시작될 때 조회한 데이터의 일관된 상태를 트랜잭션 내내 유지한다. 다른 트랜잭션이 해당 데이터를 변경하더라도, 이 트랜잭션에서는 변경사항이 반영되지 않는다.
- ex) 트랜잭션 A가 데이터 X를 조회한다. 이후 트랜잭션 B가 데이터 X를 변경하고 커밋한다. 하지만 트랜잭션 A는 여전히 최초 조회했던 시점의 데이터 X를 볼 수 있다.
SERIALIZABLE(직렬화 가능)
- 가장 엄격한 격리 수준으로, 트랜잭션들이 서로에게 아무런 영향을 주지 않는 것처럼 실행된다. 이 수준에서는 동시성이 크게 제한되며, 성능 저하가 발생할 수 있다.
- ex) 트랜잭션 A가 데이터 X와 Y를 조회한다. 이 수준에서는 트랜잭션 B가 X 또는 Y에 영향을 미치는 어떠한 작업도 수행할 수 없다. A가 완료될 때까지 B는 X나 Y와 관련된 작업을 수행할 수 없다.
아래로 내려갈수록 성능이 나빠지지만 더 안전하게 사용할수 있다.
이 강의는 READ COMMITTED(커밋된 읽기) 트랜잭션 격리 수준을 기준으로 설명한다고 한다.
데이터 베이스 연결 구조와 DB 세션
개발자가 클라이언트를 통해 SQL을 전달하면 현재 커넥션에 연결된 세션이 SQL 문을 실행하며, 이때 세션은 트랜잭션을 시작하고, 커밋 또는 롤백을 통해 트랜잭션을 종료한다. 그리고 이후에 새로운 트랜잭션을 다시 시작할수도 있다.
트랜잭션 개념 이해
데이터 변경 쿼리를 실행하고 그 결과를 반영하려면 커밋 명령어인 commit
을 호출하고, 결과를 반영하고 싶지 않으면 rollback
명령어를 호출하면 된다.
즉 commit
명령어를 호출하기 전까진 임시로 데이터를 저장한다. 따라서 해당 트랜잭션을 시작한 세션(사용자) 에게만 변경 데이터가 보이고 다른 세션(사용자)에게는 변경 데이터가 보이지 않는다.
Commit
위처럼 세션1에서 신규 회원을 추가한다.
이때 commit
을 하지 않은 상태라면 세션2에서 테이블 조회를 한 결과는 오른쪽 table과 같다.
즉 세션1 에서 아직 commit
을 하지 않았으므로 세션 2에서 테이블 조회시 아직 신규 회원 데이터가 보이지 않는다.
그후 세션 1에서 commit
을 하게 된다면 그후엔 세션2에서도 테이블 조회시 추가된 신규 회원 데이터가 보이게 된다.
Rollback
만약 Rollback
을 호출하게되면 트랜잭션을 시작한 상태로 돌아가게 된다.
즉 세션1이 DB에 반영한 모든 데이터가 처음 상태로 복구된다.
자동 커밋, 수동 커밋
트랜잭션 사용시 자동커밋 또는 수동 커밋을 설정할수 있다.
기본값은 자동 커밋이다.
자동 커밋 사용시 우리가 따로 설정할 필요없이 sql 문을 자동적으로 커밋해준다.
하지만 자동커밋 사용시 자동으로 커밋이 일어나버리기 때문에 트랜잭션 기능을 제대로 사용할수 없다.
수동커밋
set autocommit false; //수동 커밋 모드 설정
insert into member(member_id, money) values ('data3',10000);
insert into member(member_id, money) values ('data4',10000);
commit; //수동 커밋
위처럼 수동커밋을 설정해줄수있다. (관례상 수동커밋 설정이 트랜잭션의 시작을 의미한다.)
수동커밋을 설정하면 꼭 마지막에 commit
또는 rollback
을 호출해줘야 한다.
❗자동 커밋을 사용하면 결국 sql 문을 작성후 commit 또는 rollback 을 하더라도 아무런 일도 발생하지 않는다. (각각의 sql마다 자동적으로 commit이 되기 때문에)
DB 락
만약 세션1,2 가 동시에 어떠한 데이터를 동시에 수정하려한다면 트랜잭션의 원자성이 깨질수 있다.
이런 문제를 방지하기위해 하나의 세션이 특정 데이터를 수정하고 커밋이나 롤백 전까지 다른세션에서 해당 데이터를 수정할수 없게 막아야 한다.
이렇게 세션1이 세션2보다 먼저 락을 획득한다면, 세션1은 해당 row에 update를 할수있다.
이때 세션2또한 같은 데이터를 수정하기위해선 lock을 획득해야하지만 세션1이 먼저 lock을 획득후 동작하고 있으므로 세션1의 트랜잭션이 commit될때까지 기다려야한다.
❗️참고로 세션2가 무한정 기다리는건 아니다. 락 대기시간이 넘어가면 타임아웃 오류가 발생한다.
조회할때 lock을 사용하는 특수한 경우
조회는 기본적으로 세션1이 lock을 획득하고 데이터를 수정하고 있더라도 다른 세션에서 해당 데이터 조회를 할수있다.
만약 데이터를 조회하는데 다른 세션에서 해당 데이터를 조작하는걸 원치 않는다하면 select for update
구문을 사용하면 된다.
set autocommit false;
select * from member where member_id='memberA' for update;
위와같이 sql 구문을 작성한다면 다른 세션에서 해당 데이터를 조작할수 없게된다. (lock 을 가져와 해당 데이터의수정을 막는거기 때문에 조회까지 안되는건 아니다.)
결론적으로 select for update
구문을 사용하면, 내가 조회할때 다른 세션에서 해당 데이터를 조작할수는 없지만 조회는 가능하다.
Reference
'DB' 카테고리의 다른 글
Docker를 통해 Mysql 설치 (1) | 2023.11.27 |
---|---|
h2 DB 연결 방법 (1) | 2023.11.27 |
커넥션 풀 및 데이터 소스 (0) | 2023.10.25 |
JDBC (0) | 2023.10.25 |
MySQL) 프로시저를 사용하여 더미 데이터 만들기 (0) | 2023.05.04 |
커넥션 풀 및 데이터 소스
커넥션 풀

- 앱은 데이터베이스에 접근하기 위해 DB 드라이버를 사용해 연결을 시도한다.
- DB 드라이버는 데이터베이스와 특별한 네트워크 연결인 TCP/IP를 사용하여 소통한다. 여기서 3-way-hand-shake 과정이 일어나면서 안전하게 연결이 이루어 진다.
- 안전한 연결이 만들어지면, 드라이버는 우리의 사용자 이름과 비밀번호 같은 정보를 데이터베이스에 전달한다.
- 데이터베이스는 받은 정보로 사용자를 확인하고, 확인이 완료되면 데이터베이스 내부에서 사용자를 위한 공간인 '세션'을 하나 만들어 준다.
- 이 모든 과정이 잘 진행되었다면, 데이터베이스는 "연결 완료!"라는 메시지를 드라이버에게 보냅니다.
- 드라이버는 마지막으로 앱에게 만들어진 커넥션을 반환한다.
데이터 베이스 커넥션을 획득하는 과정은 위와 같다. 따라서 매번 커넥션을 만드는 과정은 매우 복잡하고 시간이 많이 소모된다. 결과적으로 응답속도에 영향을 미치며, 이것은 사용자에게도 영향을 미친다.
위와같이 매번 커넥션을 만드는 문제를 해결하기 위해 커넥션 풀이라는 것을 사용한다.

커넥션 풀에 커넥션을 미리 10개 정도 생성해주고, 추후 DB에 접근하기위해 커넥션 풀에있는 커넥션을 하나 사용해 DB에 연결을 하면 된다. 그후 사용한 커넥션은 다시 커넥션 풀에 반환한다.
❗️이때 커넥션 을 종료하는게 아닌 커넥션이 살아있는 상태로 커넥션 풀에 반환해야 한다.
✔️Spring 에서는 HikariCP 라는 커넥션 풀을 사용한다.
DataSource

DataSource란 커넥션을 획득하는 방법을 추상화하는 것이다.
만약 우리가 DriverManager 를 사용해 커넥션을 얻어 사용하다 HikariCP 커넥션 풀을 사용하여 커넥션을 획득 하는 방법을 변경했다 가정한다.
이때 애플리케이션 코드 변경을 피할수 없는데 이를 해결하기위해 DataSource 라는 표준 인터페이스를 사용한다.

javax.sql.DataSource
라는 인터페이스를 사용하여 커넥션을 획득 하는 방법을 추상화 한다.
따라서 우린 DataSource에 의존하도록 애플리케이션 로직을 작성하면 이후 커넥션을 획득 하는 과정을 변경하더라도 애플리케이션의 코드를 변경하지 않아도 된다.
DriverManger 와 DriverManagerDataSource 의 차이
@Test
void driverManager() throws SQLException {
Connection con1 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Connection con2 = DriverManager.getConnection(URL, USERNAME, PASSWORD);
log.info("connection={}, class={}", con1, con1.getClass());
log.info("connection={}, class={}", con2, con2.getClass());
}
@Test
void dataSourceDriverManager() throws SQLException {
//DriverManagerDataSource - 항상 새로운 커넥션을 획득
DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
userDataSource(dataSource);
}
private void userDataSource(DataSource dataSource) throws SQLException {
Connection con1 = dataSource.getConnection();
Connection con2 = dataSource.getConnection();
log.info("connection={}, class={}", con1, con1.getClass());
log.info("connection={}, class={}", con2, con2.getClass());
}
DriverManager
는 dataSource
인터페이스를 사용하지 않는다. 반면 DataSourceDriverManager
는 dataSource 인터페이스를 구현한 DriverManagerDataSource 를 사용하여 커넥션을 획득한다.
두 방법의 가장큰 차이는 DriverManagerDataSource는 설정정보를 초기 한번만 설정을 해주며, 그후엔 아무런 정보에 의존하지 않은채로 connection을 획득한다.
이는 설정과 사용을 분리한 것이며 이런 코드가 추후 유지보수를 할때 훨씬 편리하다.
굳이 DriverManagerDataSource
를 만들어둔 이유는, 만약 사용자가 dataSource
인터페이스를 구현하지 않는 DriverManger
를 통해 db 커넥션을 사용하고 있다가, 커넥션 풀을 사용하기 위해dataSource
를 상속받는 구현체로 바꾸고 싶다할때, 애플리케이션 로직의 변동이 필요하다.
이런 불필요한 애플리케이션 로직의 변동을 막기위해 dataSource
를 구현하면서 DriverManger
기능을 사용하기위한 DriverMangaerDataSource
를 만들어 놓은 것이다.
❗️하지만 DriverManagerDataSource 또한 DataSource의 구현체일뿐 내부적으로는 DriverManger
를 사용하기 때문에 커넥션 풀을 사용하지는 않는다.
HikariDataSourcePool (커넥션 풀)사용
@Test
void dataSourceConnectionPool() throws SQLException, InterruptedException {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
dataSource.setMaximumPoolSize(10);
dataSource.setPoolName("MyPool");
userDataSource(dataSource);
Thread.sleep(1000);
}
private void userDataSource(DataSource dataSource) throws SQLException {
Connection con1 = dataSource.getConnection();
Connection con2 = dataSource.getConnection();
log.info("connection={}, class={}", con1, con1.getClass());
log.info("connection={}, class={}", con2, con2.getClass());
}
위처럼 HikariDataSource를 사용하여 커넥션 풀에서 해당 커넥션을 가져올수있다.
해당 Test를 실행해보면 10개의 connection을 main 스레드가 아닌 adder 쓰레드 에서 생성하는 것을 볼수있다.
17:27:57.161 [MyPool connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - MyPool - Added connection conn2: url=jdbc:h2:tcp://localhost/~/test user=SA
이때 main 스레드가 아닌 별도의 쓰레드에서 커넥션 풀에 커넥션을 채우는 이유는 커넥션 풀에 커넥션을 채우는 것은 상대적으로 오래 걸린다 따라서 커넥션풀에 커넥션을 채울때까지 애플리케이션이 대기할수 없기 때문에 별도의 쓰레드를 사용하여 커넥션풀을 채우는 것이다.
또한 우리가 2개의 connection을 가져오고 그후 반환하지 않았으므로
After adding stats (total=10, active=2, idle=8, waiting=0)
위처럼 active는 2개, 대기상태인 커넥션은 8개로 나온다.
❗️만약 지금 생성한 커넥션의 크기(10개)보다 더많은 커넥션을 얻으려 한다면 이땐 block이 걸린다. 즉 사용중인 커넥션이 반환될때 까지 대기한다. 이때 해당 커넥션을 기다리는 시간또한 설정해줄수 있다.
@Test
void dataSourceConnectionPool() throws SQLException, InterruptedException {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
dataSource.setMaximumPoolSize(10);
dataSource.setPoolName("MyPool");
useAndCloseDataSource(dataSource);
Thread.sleep(1000);
reuseDataSource(dataSource);
}
private void useAndCloseDataSource(DataSource dataSource) throws SQLException {
try (Connection con1 = dataSource.getConnection()) {
log.info("First connection={}, class={}", con1, con1.getClass());
}
}
private void reuseDataSource(DataSource dataSource) throws SQLException {
try (Connection con2 = dataSource.getConnection()) {
log.info("Second connection={}, class={}", con2, con2.getClass());
}
}
//실행결과
21:17:38.837 ... First connection=HikariProxyConnection@640808588 wrapping conn0: url=jdbc:h2:mem:testdb user=SA ...
21:17:39.844 ... Second connection=HikariProxyConnection@1866229258 wrapping conn0: url=jdbc:h2:mem:testdb user=SA ...
위 코드는 HikariDataSource
를 사용하는 예시이다. DriverManagerDataSource 를 사용하면 항상 새로운 커넥션을 만든것과 다르게 HikariDataSource 를 사용하면 커넥션 풀에 있는 커넥션을 사용한다.
위코드에서 각 HikariProxyConnection
객체가 가지고 있는 커넥션이 conn0
으로 같다. 이렇게 커넥션 풀 안에 있는 코드를 사용하면 추후 커넥션을 재사용을 할수 있다.
3줄 요약
- DB 와 연결하려면 커넥션을 사용해야 하는데 이 커넥션을 매번 만드려면 시간이 오래걸린다.
- DB 커넥션 풀을 사용하여 여러 커넥션을 미리 만들어두고 DB와 연결할수 있는 커넥션을 가져온다.
- 커넥션 풀마다 커넥션을 가져오는 방법이 모두다르기 때문에, 데이터소스 인터페이스를 구현한 구현체에 의해 가져와 다른 커넥션을 사용하더라도 애플리케이션 코드의 변경을 최소화 한다.
Reference
'DB' 카테고리의 다른 글
h2 DB 연결 방법 (1) | 2023.11.27 |
---|---|
트랜잭션(transaction) (1) | 2023.11.22 |
JDBC (0) | 2023.10.25 |
MySQL) 프로시저를 사용하여 더미 데이터 만들기 (0) | 2023.05.04 |
MySQL) 서버의 MySQL intellij로 연동하기 (0) | 2023.05.04 |
JDBC
JDBC 이해
JDBC(Java Database Connectivity) : 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API 이다.
JDBC 가 등장한이유는 이전에는 각 DB를 사용하는 방법이 모두 달랐다.(커넥션 연결, SQL 전달, 결과 응답) 즉 Oracle DB를 사용하다 MySQL로 DB를 바꿔야 하면 애플리케이션 서버에 있는 코드또한 수정을 필요로했다.
따라서 JDBC를 활용해 자바에서 DB에 접근하는 방법을 통일했다.

즉 JDBC 표준 인터페이스를 정의한후 이 인터페이스만을 사용하여 DB에 접근하도록 했다.
이때 인터페이스의 구현체는 각 DB의 회사에서 라이브러리 형식으로 제공하며 이를 JDBC 드라이버 라고 한다.
❗️하지만 JDBC를 사용하더라도 SQL은 각각의 데이터베이스마다 사용법이 다르다. 즉 JDBC의 등장으로 JDBC코드는 변경을 하지 않아도 되지만, SQL은 해당 데이터 베이스에 맞도록 변경해야한다. SQL이 다른 문제는 JPA(Java Persistance API)를 사용하면 어느정도 해소가 가능하다.
최신 JDBC
최근엔 JDBC를 편리하게 사용하는 다양한 기술이 존재하며, 대표적으로 SQL Mapper와 ORM 기술이 있다.
- SQL MapperSQL Mapper를 사용하면 JDBC를 편리하게 사용할수 있지만, 개발자가 SQL을 직접 작성해야한다.
-
- ORM 기술ORM은 객체를 DB의 테이블과 매핑해준다. 이 덕에 개발자가 직접 SQL을 작성하지 않아도 ORM이 스스로 SQL을 동적으로 만들어 실행해준다. (DB마다 서로다른 SQL을 사용하는 문제도 중간에 해결해준다.)
-
❗️SQL Mapper 나 ORM을 사용하더라도 JDBC를 항상 사용한다. 따라서 JDBC의 기본 원리에 대해서 꼭 알아두어야 한다.
DB 연결및 DriverManager
DB에 연결하기 위해선 JDBC가 제공하는 DriverManager.getConnection(..)을 사용하면 된다.
public static Connection getConnection() {
try {
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return connection;
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
이렇게 하면 라이브러리에 있는 DB 드라이버를 찾아 해당 드라이버가 제공하는 커넥션을 반환해 준다.
여기선 H2 DB 드라이버가 작동해 실제 DB와 커넥션을 맺고 그 결과를 반환한다.
즉 우리가 H2와 연결하기위해선 java.sql.Connection
interface를 구현하고있는 구현체(H2 커넥션)이 필요하다.
이 커넥션을 Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
여기서 얻어온거고, 이 걸통해 db와 상호작용 할수 있는 것이다.
이때 어떻게 우리가 h2 의 드라이버를 로드할수 있을까? MySQL을 사용할수도 있고 그외 DB를 사용할수도 있다.
위 코드에서 우린 h2랑 연결한다는 어떠한 정보도 주지 않는것처럼 보인다.

JDBC가 제공하는 DriverManager는 라이브러리에 등록된 DB 드라이버를 관리하며, 커넥션을 획득하는 기능을 제공한다.
즉 DriverManager는 라이브러리에 등록된 드라이버 목록을 자동으로 인식하며, 이 드라이버들에게 정보를 넘겨 커넥션을 획득 할 수 있는지 확인한다.
아래와 같은 .yml
파일이 있다 가정한다.
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
h2 DB를 사용한다는 가정하에 URL은 위에 보이는것 처럼 URL = "jdbc:h2:~~~"
이다. 이때 DriverManager는 해당 URL을 각각의 드라이버에게(h2, MySQL) 넘겨준후 해당 URL을 처리할수 있는 드라이버를 찾으면 해당 드라이버를 통해 실제 DB에 연결해 커넥션을 찾고 그 커넥션을 반환해 주는 것이다.
🙏Reference
'DB' 카테고리의 다른 글
트랜잭션(transaction) (1) | 2023.11.22 |
---|---|
커넥션 풀 및 데이터 소스 (0) | 2023.10.25 |
MySQL) 프로시저를 사용하여 더미 데이터 만들기 (0) | 2023.05.04 |
MySQL) 서버의 MySQL intellij로 연동하기 (0) | 2023.05.04 |
MySQL) ubuntu에 MySQL 설치 (0) | 2023.05.04 |
MySQL) 프로시저를 사용하여 더미 데이터 만들기
더미 데이터 생성
프로시저 생성
- 프로시저(Stored Procedure)란, 데이터베이스 내에서 쿼리문과 같은 역할을 하지만, 한번의 호출로 여러 쿼리를 실행하거나, 조건문 등을 이용하여 특정 작업을 처리하는 등의 여러 가지 기능을 수행할 수 있는 데이터베이스 객체다.
예를 들어 프로시저를 사용하여 100개의 게시글을 만들고 싶다면 아래와 같은 프로시저를 실행하면 된다.
DELIMITER $$
DROP PROCEDURE IF EXISTS loopInsert$$
CREATE PROCEDURE loopInsert()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 100
DO
INSERT INTO ARTICLE(title, content, user_id)
VALUES (concat('제목', i), concat('내용', i), 'tester');
SET i = i + 1;
END WHILE;
END$$
DELIMITER ;
그후
CALL loopInsert();
프로시저를 호출하여 실행해주면 된다.
만약 위 프로시저를 실행한후 100~300 까지의 게시글을 추가적으로 만들고싶다면 아래와 같은 프로시저를 사용하면 된다.
DELIMITER $$
DROP PROCEDURE IF EXISTS loopInsert$$
CREATE PROCEDURE loopInsert()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 300
DO
IF i >= 100 THEN
INSERT INTO ARTICLE(title, content, user_id)
VALUES (concat('제목', i), concat('내용', i), 'tester');
END IF;
SET i = i + 1;
END WHILE;
END$$
DELIMITER ;
'DB' 카테고리의 다른 글
커넥션 풀 및 데이터 소스 (0) | 2023.10.25 |
---|---|
JDBC (0) | 2023.10.25 |
MySQL) 서버의 MySQL intellij로 연동하기 (0) | 2023.05.04 |
MySQL) ubuntu에 MySQL 설치 (0) | 2023.05.04 |
MySQL) 사용자 추가 (0) | 2023.05.04 |