Reactive Relational DataBase Connectivity (R2DBC) 는 JPA,JDBC등으로 사용하던 Blocking 기반 RDB를 Reactive 하게 사용할 수 있도록 API 를 제공한다. WebFlux 와 R2DBC 를 사용하는 경우 애플리케이션이 온전히 Reactive 하게 동작할 수 있도록 지원한다.
JDBC는 동기 Blocking I/O 기반으로 설계된 데이터베이스 연결 라이브러리이다.
JPA는 JDBC를 사용해서 데이터베이스와 객체를 잘 매핑해주는 기술로 Blocking I/O기반임은 똑같다.
이러한 이유로 WebFLux와 같이 Non-Blocking Reactive 환경에서 사용하게 되면 Blocking되는 현상이 발생한다.
다음과 같은 인터페이스들 제공
- 연결 (Connection Factory 등등)
- 에러 핸들링
- transaction 관련 기능
구문
bind: sql에 파라미터를 binding하는 구문
&#xNAN;add : 이전 까지의 binding을 저장 후 새로운 binding생성
&#xNAN;execute : 생성된 binding만큼 쿼리를 실행 후 결과를 Publisher 형태로 제공
MySqlConnectionFactory
MySqlConnection 객체를 Mono형태로 가지고 있음.
싱글톤 패턴으로 구현되어 있음.
MySqlConnectionConfiguration
MySQL 연결 설정을 포함하는 객체
host, port, database, username, password등의 기본 설정을 제공
var connectionFactory = MySqlConnectionFactory.from(config);R2dbcEntityTemplete
spring data r2dbc의 추상화 클래스
결과를 entity객체로 받을 수 있음.
var template = new R2dbcEntityTemplate(connectionFactory)R2dbcEntityOperations
R2dbcEntityTemplate가 상속하고 있는 기능들에 대한 클래스이다.
여기에는
Select : ReactiveSelectOperation
Insert : ReactiveInsertOperation
Update : ReactiveUpdateOperation
Delete : ReactiveDeleteOperation
기본적인 예제
Select 예제
val r2dbcTemplate = R2dbcEntityTemplate(connectionFactory)
var query = Query.query(
Criteria.where("name").is("ABC")
)
r2dbcTemplate.select(User::class.java)
.from("user")
.matching(query)
.first()
.doOnNext{
it->log.info{it}
}
.subscribe()Update 예제
val r2dbcTemplate = R2dbcEntityTemplate(connectionFactory)
var query = Query.query(
Criteria.where("name").is("ABC")
)
var update = Update.update("name","XYZ")
r2dbcTemplate.update(User::class.java)
.inTable("user")
.matching(query)
.apply(update)
.doOnNext{
it->log.info{it}
}
.subscribe()더 쉽게 사용하도록 구현된 방식
r2dbcTemplate.select(query,User::class.java) //selcet
r2dbcTemplate.insert(user) // insert
r2dbcTemplate.update(user) //updateJPA의 JPA Repository 인터페이스 처럼 R2DBC에서 CRUD와 같은 기본적인 기능들이 작성되어있는 인터페이스
기본적인 기능이나 함수명등등 JPA Repository와 거의 동일함.
R2DBC Repository의 기능들이 구현되어있는 구현체이다.
하지만 n개의 결과만 가져오는 등의 기능은 제공되지 않기 때문에 쿼리 메소드를 사용해야한다
복잡한 쿼리들을 미리 작성해둬서 실행하는 방법 JPA에서 @Query어노테이션과 동일
업데이트 예제
@Modifying
@Query("update user set name = :name where id = :id")
fun updateNameById(String name, Long id) : Mono<Integer>