書接上回通過Spring Initializr創建mysql項目坑(一),雖然不再報錯誤了,但是我們運行代碼后發現初始化sql沒有執行,這就是springboot2.1.4datadource坑之二schema不執行。
錯誤二
現象
yml文件中的schema沒有執行
問題分析
-
判斷文件是否加載,修改成一個不存在sql文件,看是否加載文件
image.png
可以看到SpringBoot試圖加載了該Schema,但是沒有找到這個錯誤的文件名,這就證明了系統啟動時加載了文件。
相關錯誤信息如下
2019-04-12 18:14:34.977 ERROR 13276 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker': Invocation of init method failed; nested exception is org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException: Property spring.datasource.schema with value 'class path resource [sinit.sql]' is invalid: The specified resource does not exist.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-5.1.6.RELEASE.jar:5.1.6.RELEASE]
-
將Schema修改為正確的文件名,修改sql內容為不合法語句,看sql是否執行
image.png
運行發現并沒有出現任何錯誤
image.png - 通過第一步和第二步的操作我們可以得出結論
- SpringBoot在啟動時加載了schema文件
- SpringBoot啟動時并沒有去運行改shema文件
- 同時結合第一步操作的異常日志我們看到一個需要關注的類
org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker
-
通過異常定位代碼位置,進行源代碼跟蹤
我們打開DataSourceInitializerInvoker類,通過代碼我們進一步斷定了這個類和schema的執行是相關,然后我們在該類的方法中都增加斷點,然后以debug方式運行。
image.png
運行后進入了第一個斷點afterPropertiesSet(),我們單步執行到createSchema方法,通過這個名字能很容易判斷是執行shema的語句,我們進入這個方法進行調試
進入DataSourceInitializer中的createSchema方法,可以看到這里有一個isEnabled的判斷,如果不允許的話就輸出debug日志返回,如果允許的話才執行scheme腳本。
我們繼續跟進isEnabled(),看看為什么的示例中會按照"不允許"執行的。
而我們的示例中,mode為EMBEDDED,滿足了第二個if判斷,所有返回false,這樣也就使得我們的schema腳本沒有得到執行。
我們打開DataSourceInitializerMode發現有三種不同的模式,always為始終執行初始化,embedded只初始化內存數據庫,never為不執行初始化。
通過mode=this.properties.getInitializationMode()我們能推斷initializationMode應該是可以配置的一個參數,而系統默認值為EMBEDDED
解決辦法
找到了問題,辦法就好說了。
我們只要將initializationMode修改為always,就應該能執行我們的schema初始化腳本。怎么修改呢?
當然是在yml中修改,在schema上增加一行與shema同級別的
initializationMode: always
再次運行程序,圓滿解決!
上一篇
通過Spring Initializr創建mysql項目坑(一) |
---|