### 歡迎訪問我的GitHub > 這裡分類和彙總了欣宸的全部原創(含配套源碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### 本篇概覽 - 本篇內容並非資料庫相關的核心知識,而是對 ...
歡迎訪問我的GitHub
這裡分類和彙總了欣宸的全部原創(含配套源碼):https://github.com/zq2599/blog_demos
本篇概覽
-
本篇內容並非資料庫相關的核心知識,而是對一個實用工具的說明介紹,此工具在官方介紹中被稱為Zero Config Setup (Dev Services),(零配置的設置,忒莫名其妙)
-
我這邊簡單總結為:如果你沒有資料庫可用,只要你有docker,quarkus應用就能進行資料庫相關的開發工作,增刪改查啥都行,和有資料庫的時候沒啥區別
-
看到這裡,經驗豐富的您應該會覺得:既然有docker,那麼用docker run裝一個資料庫不就行了嗎,和quarkus工具有啥關係?
-
其實這個Zero Config Setup還算是有那麼一點自己的特色,和自己動手在docker中裝資料庫有一丟丟區別,我做了個對比圖如下
-
可見Zero Config Setup的好處是啥都不用配,有docker就行,劣勢是必須要用mvn quarkus:dev啟動應用,profile固定是dev
-
看到這裡,您是否會這麼覺得:哦,知道了,那我去建一個application-dev.properites文件,裡面沒有資料庫配置,然後執行mvn quarkus:dev啟動應用就行了,就這點內容唄,欣宸你別寫了,太啰嗦...
-
確實內容少,但是它有坑啊,所以請您隨本文一同實戰吧,等到操作成功的那一刻,新技能get帶來的舒適感相信您也不會拒絕,然後用起Zero Config Setup直呼666
-
接下來咱們親自動手體驗這個Zero Config Setup,看看適不適合開發階段使用
關於資料庫操作的源碼
- quarkus操作資料庫的代碼,就直接用前文《quarkus資料庫篇之一》的代碼吧,除了從前文拷貝,您也可以在我的GitHub倉庫下載,,地址和鏈接信息如下表所示(https://github.com/zq2599/blog_demos)
名稱 | 鏈接 | 備註 |
---|---|---|
項目主頁 | https://github.com/zq2599/blog_demos | 該項目在GitHub上的主頁 |
git倉庫地址(https) | https://github.com/zq2599/blog_demos.git | 該項目源碼的倉庫地址,https協議 |
git倉庫地址(ssh) | [email protected]:zq2599/blog_demos.git | 該項目源碼的倉庫地址,ssh協議 |
- 這個git項目中有多個文件夾,本次實戰的源碼在quarkus-tutorials文件夾下,如下圖紅框
- quarkus-tutorials是個父工程,裡面有多個module,本篇實戰的module是basic-db,如下圖紅框
提前下載docker鏡像
- 建議先把鏡像下載到本地才能使用Zero Config Setup功能,否則如果等quarkus框架自動下載鏡像,可能會有如下錯誤發生
[INFO] Compiling 1 source file to /Users/zhaoqin/github/blog_demos/quarkus-tutorials/basic-db/target/test-classes
Listening for transport dt_socket at address: 5005
2022-05-08 10:52:56,714 ERROR [com.git.doc.api.asy.ResultCallbackTemplate] (docker-java-stream-1954350275) Error during callback: com.github.dockerjava.api.exception.InternalServerErrorException: Status 500: {"message":"Head \"https://registry-1.docker.io/v2/testcontainers/ryuk/manifests/0.3.3\": unauthorized: incorrect username or password"}
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:247)
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269)
at java.base/java.lang.Thread.run(Thread.java:829)
2022-05-08 10:52:57,019 INFO [io.qua.dep.dev.IsolatedDevModeMain] (main) Attempting to start live reload endpoint to recover from previous Quarkus startup failure
2022-05-08 10:52:57,037 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.datasource.deployment.devservices.DevServicesDatasourceProcessor#launchDatabases threw an exception: java.lang.RuntimeException: com.github.dockerjava.api.exception.InternalServerErrorException: Status 500: {"message":"Head \"https://registry-1.docker.io/v2/testcontainers/ryuk/manifests/0.3.3\": unauthorized: incorrect username or password"}
at io.quarkus.datasource.deployment.devservices.DevServicesDatasourceProcessor.startDevDb(DevServicesDatasourceProcessor.java:314)
at io.quarkus.datasource.deployment.devservices.DevServicesDatasourceProcessor.launchDatabases(DevServicesDatasourceProcessor.java:121)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.quarkus.deployment.ExtensionLoader$2.execute(ExtensionLoader.java:882)
at io.quarkus.builder.BuildContext.run(BuildContext.java:277)
at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at java.base/java.lang.Thread.run(Thread.java:829)
at org.jboss.threads.JBossThread.run(JBossThread.java:501)
Caused by: com.github.dockerjava.api.exception.InternalServerErrorException: Status 500: {"message":"Head \"https://registry-1.docker.io/v2/testcontainers/ryuk/manifests/0.3.3\": unauthorized: incorrect username or password"}
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:247)
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269)
at java.base/java.lang.Thread.run(Thread.java:829)
- 為了避免上述錯誤,以下兩種方式都可以,請您二選一即可
- 提前下載docker鏡像,命令是docker pull testcontainers/ryuk:0.3.3(當您看到此文是,tag可能不是0.3.3了,你可以從錯誤信息中確定您那邊的tag)
- 如果您有docker賬號,執行命令docker login index.docker.io登錄docker
dev這個profile的配置文件
- 新增名文件application-dev.properties,裡面就一行內容
quarkus.hibernate-orm.sql-load-script=import.sql
- 可見和之前的application-test.properties相比,dev這個profile下的配置文件中,不能有任何資料庫配置(資料庫IP、埠、庫名、賬號、密碼等)
啟動應用
- 進入目錄quarkus-tutorials/basic-db,執行命令mvn quarkus:dev啟動應用,控制台輸入如下
[INFO] Nothing to compile - all classes are up to date
Listening for transport dt_socket at address: 5005
2022-05-08 17:51:48,010 INFO [io.qua.dat.dep.dev.DevServicesDatasourceProcessor] (build-12) Dev Services for the default datasource (postgresql) started.
2022-05-08 17:51:48,011 INFO [io.qua.hib.orm.dep.HibernateOrmProcessor] (build-5) Setting quarkus.hibernate-orm.database.generation=drop-and-create to initialize Dev Services managed database
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2022-05-08 17:51:48,244 INFO [io.agr.pool] (Quarkus Main Thread) Datasource '<default>': Initial size smaller than min. Connections will be created when necessary
Hibernate:
drop table if exists known_fruits cascade
2022-05-08 17:51:48,510 WARN [org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread: <default>) SQL Warning Code: 0, SQLState: 00000
2022-05-08 17:51:48,511 WARN [org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread: <default>) table "known_fruits" does not exist, skipping
Hibernate:
drop sequence if exists known_fruits_id_seq
2022-05-08 17:51:48,512 WARN [org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread: <default>) SQL Warning Code: 0, SQLState: 00000
2022-05-08 17:51:48,512 WARN [org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread: <default>) sequence "known_fruits_id_seq" does not exist, skipping
Hibernate: create sequence known_fruits_id_seq start 10 increment 1
Hibernate:
create table known_fruits (
id int4 not null,
name varchar(40),
primary key (id)
)
Hibernate:
alter table if exists known_fruits
add constraint UK_57g3m8wr3qxoj706a6hsqg6ye unique (name)
Hibernate:
INSERT INTO known_fruits(id, name) VALUES (1, 'Cherry')
Hibernate:
INSERT INTO known_fruits(id, name) VALUES (2, 'Apple')
Hibernate:
INSERT INTO known_fruits(id, name) VALUES (3, 'Banana')
2022-05-08 17:51:48,558 INFO [io.quarkus] (Quarkus Main Thread) basic-db 1.0-SNAPSHOT on JVM (powered by Quarkus 2.7.3.Final) started in 2.706s.
2022-05-08 17:51:48,559 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2022-05-08 17:51:48,559 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, jdbc-postgresql, narayana-jta, smallrye-context-propagation]
--
--
Tests paused
Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>
- 從上述信息可見,即便是沒有資料庫,也沒有資料庫配置,quarkus也會通過docker為應用把資料庫備好,讓應用順利啟動、連接、執行初始化SQL
執行單元測試
- 從上述控制台信息可見,目前的控制條已經處於命令行交互模式,先輸入o開啟測試日誌輸出開關
- 然後再輸入r開始執行單元測試,控制台輸出如下,可見和上一篇的操作並沒有什麼區別(還省去了資料庫的部署和配置)
- 至此,Zero Config Setup的體驗就完成了,雖然省去了資料庫的部署和配置,但profile被限定在dev,這怕是很多人不情願的,另外這都是後臺命令的操作,IDEA的單元測試頁面也不知道如何與quarkus的dev模式結合起來用,又是個巨大損失,所以,Zero Config Setup到底適不適用也是見仁見智
接受資料庫的license
- 如果您用的資料庫是DB2或者MSSQL,在使用Zero Config Setup的時候會涉及到接受license的操作,您需要新增文件src/main/resources/container-license-acceptance.txt,內容如下,就是資料庫的鏡像名
ibmcom/db2:11.5.0.0a
mcr.microsoft.com/mssql/server:2017-CU12
MySQL的配置
- 在使用MySQL的時候,我們可能對其做一些配置,那麼Zero Config Setup提供的MySQL就無法滿足我們的需求了,這裡可以通過配置來指定MySQL配置信息(個人的感覺,就是為瞭解決一個問題而引入了新的問題)
quarkus.datasource.devservices.container-properties.TC_MY_CNF=testcontainers/mysql-conf
發現神秘信息
-
接下來聊聊一次偶然的發現,既有驚喜也有疑惑,還希望親愛的讀者能夠給予指導和建議
-
回想一下,當您使用mvn quarkus:dev啟動應用後,控制台提示如下信息
Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>
- 於是,我按照上述提示輸入冒號,進入quarkus的終端模式,控制條提示如下
You are now in Quarkus Terminal. Your app is still running. Use `help` or tab completion to explore, `quit` or `q` to return to your application.
quarkus$
- 然後,輸入postgres print-command,就會看到quarkus創建的資料庫信息,賬號、密碼、埠、庫名、啥都有,如下,真是神奇啊
quarkus$ postgres print-command
PGPASSWORD=quarkus psql --host=localhost --port=49294 --username=quarkus default
- 上述信息,應該是quarkus在docker上創建的資料庫信息,於是我興衝衝地用IDEA的資料庫工具去連接這個資料庫,如下圖,天哪,連接成功了
- 然後查看表的數據,如下圖,正是初始化腳本import.sql中新增的內容
-
本以為發現了quarkus的驚天秘密,今後開發中隨時可以連接此資料庫查看數據,結果發現單元測試對數據的任何寫操作,都不會改變上圖表中的內容,這和使用自己的資料庫是完全不同的,上一篇文章中,咱們執行完單元測試後,寫操作的結果在資料庫中是可以查到的
-
目前還沒有查到上述問題的原因,估計是quarkus自己內部的處理機制吧,例如自動rollback,或者某些程度的可見性隔離等,這都是猜的,親愛的讀者,如果您知道了原因,麻煩您在回覆中指點一二,謝謝了
-
其實這也不是什麼問題,不去查那個表就行了,單元測試的讀寫功能是正常的,也就是說單元測試中,數據發生變化後程式可以讀取到變化後的數據,只是我們用工具看不到變化而已(官方文檔也沒有提及用工具去連接那個表,應該是不推薦這麼做)
-
至此,quarkus的Zero Config Setup體驗完成,希望這個小技能可以對您有所幫助,以更簡單的操作度過編碼和自測的時光