Java에서 제공하는, DB 접근 관련 API
Java DataBase Connectivity의 약자다.
JDBC를 위한 Template
이다.
Spring에 있는 Template
부류의 class다. Spring Data에 추가된게 아니라 원래 Spring에서부터 있었다.
예시 코드에서는 이를 활용해가지고 data 획득, data store을 구현하고 있다.
진짜 최소한의 DB 접근 관련 추상화에 대해 Spring Data에서는 Operations
라는 것을 제공한다. MongoOperations
, RedisOperations
, CasandraOperations
... 앞부분 이름을 보면 다 DB Management system들이며 저 Operations
들은 각 system과 관련된 규격화된 추상화다. '최소한으로'. 이 추상화를 기반으로 더 상위의 추상화를 만드는 것이 가능하다. 대표적인게 바로 Repository
다.
이 Operations
들은 사실 전부 interface
로 정의되어 있다. 즉 Operations
는 Spring에서 지정한, 각 DB management system에 대해서 최소환의 규격화된 추상화들이 지켜야 할 틀을 제공해주는 것이다. 그러면 이 틀을 왜 만들었냐, 사실 그것들을 수행하는데에도 내부적으로 엄청 많은 boilerplate code가 존재하기 때문이다. 이는 접근을 위한 연결 관리와 뒷처리 등과 관련된 코드가 대부분이다.
Operations
에 있는 틀만 만족하도록 딱 구현한 것이 바로 Template
이다. 즉 Template
은 최소한의 data 접근 관련 추상화에 대해 직접 구현한 class들을 일컫는 class라고 생각하면 된다.
Templates
같은 것들을 흔히 Service Provider Interface, 줄여서 SPI 라고 한다. 왜냐하면 boiler plate code 부분이 없도록 구현한 API를 만들어준 다음에 그걸 활용해서 원하는 것을 뭐든 하는게 가능하기 때문이다. 하지만 다른 말로 흔히 사용되는 기능들을 구현하려면 이 API를 기반으로 추가적으로 구현할게 많이 필요하다는 것을 의미한다. 만약 그것들이 이미 존재하는 class들에서 구현해놓은 기능들이라면 (ex Repository
) 그 API를 활용하는 것이 훨씬 낫다. 예를들어 Repository
에서 제공하는 기능들만으로 충분하다면 그냥 Repository
를쓰는 것이 피곤함이 덜하다는 것이다. 대신 그런곳에서 제공 못하는, 본인만의 DB조작에 관한 커스터마이제이션이 필요한 경우 유용하다고 볼 수 있다.
비공개 글에서 자세히 설명했었다.
Dependency Injection을 명시적으로 하는 것이라고 생각하면 된다.
관련 비공개 글 (접근불가)
예시 코드처럼 autowiring을 하는 것은 추천이 안되고 대신 constructor을 통해 집어넣는 것이 추천이 된다. 이것도 비공개 글을 읽으면 이해가 될거다.
constructor을 통해 injection을 하는 경우 @Autowired
annotation은 사실 필요가 없다. constructor 종류가 1개이기 때문. 2개 이상일때만 지목하는 것이 보통 필요하다. (Spring 4.3부터만 가능하다.)
JdbcTemplate
bean은 IoC container이 실행하면서 자동으로 만들어놓고 application class에다가 주입을 한다. spring-jdbc
가 있기 때문이라고 하는데, 정확히는 spring-starter-jdbc
때문이라고 생각하면 된다. 프로젝트 생성시의 initializr에서 dependency 집어 넣을 때 넣었다.
먼저 유의할게, 동작에 사용될 H2 database는 자동으로 생성된다. starter 형태로 미리 dependency에 넣었기에 거기서 생성.
execute
: DDL을 활용하는 method. 여기서는 DDL 프로그램을 통해 DB table 조작을 좀 먼저 했다.
이후 집어넣을 data를 미리 준비.
log에 data를 집어넣는다고 미리 표기
batchUpdate
를 활용해가지고 bulk load DB에 수행
이후 query
를 통해 DB에서 원하는 정보를 취득.
관련 로그
2024-01-05T21:42:33.035+09:00 INFO 21180 --- [ main] .e.r.RelationaldataaccessJdbcApplication : Creating tables
2024-01-05T21:42:33.037+09:00 INFO 21180 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2024-01-05T21:42:33.170+09:00 INFO 21180 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:2b6a3ed2-86ba-45cc-972b-40aaca5fa930 user=SA
2024-01-05T21:42:33.171+09:00 INFO 21180 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2024-01-05T21:42:33.183+09:00 INFO 21180 --- [ main] .e.r.RelationaldataaccessJdbcApplication : Inserting customer record for John Woo
2024-01-05T21:42:33.184+09:00 INFO 21180 --- [ main] .e.r.RelationaldataaccessJdbcApplication : Inserting customer record for Jeff Dean
2024-01-05T21:42:33.184+09:00 INFO 21180 --- [ main] .e.r.RelationaldataaccessJdbcApplication : Inserting customer record for Josh Bloch
2024-01-05T21:42:33.184+09:00 INFO 21180 --- [ main] .e.r.RelationaldataaccessJdbcApplication : Inserting customer record for Josh Long
2024-01-05T21:42:33.194+09:00 INFO 21180 --- [ main] .e.r.RelationaldataaccessJdbcApplication : Querying for customer records where first_name = 'Josh':
2024-01-05T21:42:33.204+09:00 INFO 21180 --- [ main] .e.r.RelationaldataaccessJdbcApplication : Customer[id=3, firstName='Josh', lastName='Bloch']
2024-01-05T21:42:33.205+09:00 INFO 21180 --- [ main] .e.r.RelationaldataaccessJdbcApplication : Customer[id=4, firstName='Josh', lastName='Long']
2024-01-05T21:42:33.208+09:00 INFO 21180 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2024-01-05T21:42:33.209+09:00 INFO 21180 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
https://github.com/baekrang256/Backend-Practice/tree/main/relationaldataaccessJDBC