mariadb/mysql R2DBC(CRUD)方式接入spring boot (二)
阿新 • • 發佈:2021-01-30
技術標籤:springboot資料庫spring bootspringmysql
依然是start.spring.io建立,大致的依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</ groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb</groupId>
<artifactId>r2dbc-mariadb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
< groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
使用kotlin需要再加入:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor.kotlin</groupId>
<artifactId>reactor-kotlin-extensions</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-reactor</artifactId>
</dependency>
配置資料庫和(一介紹的一樣)
spring:
r2dbc:
username: user
password: psw
url: r2dbc:mariadb://hostname:port/dataname
新建一個實體類例如:
import org.springframework.data.annotation.Id
class Customer(val firstName: String, val lastName: String) {
@Id
var id: Long? = null
override fun toString() = String.format(
"Customer[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName
)
}
新建一個初始化bean來執行初始化sql(此bean同樣適用於方式一)
@Bean
fun initializer(): ConnectionFactoryInitializer {
val initializer = ConnectionFactoryInitializer()
initializer.setConnectionFactory(connectionFactory)
initializer.setDatabasePopulator(ResourceDatabasePopulator(ClassPathResource("schema.sql")))
return initializer
}
schema.sql 如下:
DROP TABLE IF EXISTS customer;
CREATE TABLE IF NOT EXISTS customer (id SERIAL PRIMARY KEY, first_name VARCHAR(255), last_name VARCHAR(255)) CHARSET=utf8;
建立實體類倉庫:
import org.springframework.data.repository.reactive.ReactiveCrudRepository
interface CustomerRepository : ReactiveCrudRepository<Customer?, Long?>
在RestController中使用:
class cot (
val customerRepository: CustomerRepository
) { ... }
以上java的寫法就結束了
spring.io官網Going Reactive with Spring, Coroutines and Kotlin Flow有提到kotlin支援,推薦kotlin倉庫的寫法是這樣的:
import org.springframework.data.repository.kotlin.CoroutineCrudRepository
interface CustomerRepository2: CoroutineCrudRepository<Customer,Long> {
}
根據說明這是一個協程倉庫,經過測試crud速度跟spring mvc下速度接近,但是可以利用協程併發。
以下是對這些倉庫方法的測試。
測試資料庫為遠端騰訊雲上自己假設的,mariadb資料庫(有網路延遲),測試全部為單插入500條資料(用save而不是saveAll)
測試1介面,使用響應式方式調ReactiveCrudRepository介面(時間約10-300毫秒,第一次最慢,幾次後加快)非常快
@GetMapping("insert1")
fun insert1(): Long {
val time = System.currentTimeMillis()
Flux.range(1,500).flatMap { customerRepository.save(Customer("abc","bcd")) }.subscribe()
return System.currentTimeMillis() - time
}
測試2, 使用響應式方式調ReactiveCrudRepository介面(時間約70-300毫秒)非常快接近第一種
@GetMapping("insert2")
fun insert2(): Long {
val time = System.currentTimeMillis()
(1..500).forEach { _ -> customerRepository.save(Customer("abc","bcd")).subscribe() }
return System.currentTimeMillis() - time
}
測試3 ,使用CoroutineCrudRepository介面迴圈(時間快接近20000毫秒,不忍直視)
@GetMapping("insert3")
suspend fun insert3() = measureTimeMillis {
(1 ..500).forEach{ _ -> customerRepository2.save(Customer("abc","bcd"))}
}
契而不捨,官網推薦用法怎麼可能,不停的修改介面程式碼(時間1100-1400毫秒,最大努力了)
@GetMapping("insert5")
suspend fun insert5() = measureTimeMillis {
foo().buffer().collect { it.await() }
}
suspend fun foo() = flow {
coroutineScope {
for (i in 1..500) {
emit(async { customerRepository2.save(Customer("abc", "bcd")) })
}
}
}
可能還是kotlin flow用的不夠好,有更好的可以留言。
對比響應式的插入速度,如果現在開發新專案還選擇jdbc的,實在對不起金主啊!
推薦大家使用
ReactiveCrudRepository
方式CRUD