Springboot Jpa 有關多數據源的問題

前言

  一直以來,都有一個很嚴重的問題是,有些操作需求是百度上一搜出來一大把的,然後跟着別人的博文跟步操作了之後,結果就是會遇到很多其他問題,然後就會明明一個很簡單的操作,還是花費了很長時間,甚至在這過程中遇到新的問題,很難自己去着手解決,無從下手。這個時候我是怎麼做的呢?求助別人。那麼別人爲什麼會,我就不知道怎麼解決呢?其實主要的問題還是覺得我們對這個代碼操作的原理不清楚,還有一點就是沒做過本能的有種害怕或者說是新知識的抗拒吧。

  我儘可能對自己每個遇到的問題進行總結,以致於反思自己爲什麼這麼菜?

  這次的問題是,我需要在一個項目裏面連兩個數據庫,多數據源操作,這個是一個很基本的操作,大概我還是花了三四天的時間吧(並不是全天在解決這個問題,但是有在想解決思路)。

心路歷程

  • 這個沒做過啊,這要怎麼寫,就項目的單數據庫連接我都不明白原理,爲什麼需要做這樣的配置,多數據源操作本能的把他歸結爲一類很難的問題

    (我想這裏我確實應該瞭解一下架構方面的東西,目前我只是停留在會使用的階段)

 

  • 百度:“Spring boot Jpa 多數據源”,我的習慣向來不是看到一個就去試,而是我會把幾頁的百度結果都去大致的看一遍,或許我是在試圖找個最簡便的吧,但實際上是相同的操作不能人的博客描述是不一樣的,實現方式都是類似的話,我就會找一個版面比較整齊的博客參照

        參考博文:https://www.cnblogs.com/fernfei/p/12119601.html

  我根據以上博文進行了一系列的配置,我整個項目也都運行不起來了,第一天過去了。

java.sql.SQLException: net.sf.log4jdbc.DriverSpy
	at com.alibaba.druid.util.JdbcUtils.createDriver(JdbcUtils.java:653)
	at com.alibaba.druid.pool.DruidDataSource.resolveDriver(DruidDataSource.java:1212)
	at com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:887)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1383)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1379)
	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:109)
	at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:151)
	at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:115)
	at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:78)

  對這個錯誤進行百度,基本上都是有關丟包的錯誤,需要加入什麼的jar類似這樣的,實際解決方法如下。因爲在application.yml裏面有相關配置,我也不知道這個問題的解決方向。(同事幫忙解決)

 

  • 解決了上述問題之後,項目還是沒有成功運行起來,具體的錯誤已經不記得了。然後同事推薦一個博文“動態切換數據庫”,第二天過去了

  參考博文:https://blog.csdn.net/shentan0000/article/details/116274449

 

  • 我根據上述博文的操作,我成功了,可以在前端對兩個不同數據庫的api請求都成功的獲取數據了。接着就遇到致命的問題是,在一個會話中(方法中)同時做兩個庫的操作,就會直接報異常。第三天過去了

  報錯提示:對象 名“表名”無效。這裏並不是真的不存在這個表,而是連接的數據源不對,所以導致了找不到對應表。

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: 對象名 'so_xxx' 無效。

   針對動態切換數據源的操作,在一個方法裏面同時更新兩個數據源數據的操作,至今沒得到解決。

 

  • 我就想啊想,我也想不通爲什麼。這大概是我得出來的結論。第四天

 

  • 那麼根據得出來的結論,要麼同時兩個數據庫連接存在,要麼切斷連接建立新的連接。最終選擇了回到最初的配置方式。

  參考博文:https://blog.csdn.net/taojin12/article/details/88573580

  畢竟我們是要以解決同時操作兩個數據庫問題爲目標,所以沒對動態切換數據源做更深的研究。(但其實我是很有興趣弄明白他是爲什麼不能實現的)

 

  • 配置完後遇到的第一個問題
Application failed to start due to an exception

org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'PxxMainRepository' defined in null: Cannot register bean definition [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] for bean 'POMainRepository': There is already [Root bean: class [org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound.
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:894)
	at org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn(RepositoryConfigurationDelegate.java:173)
	at org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport.registerBeanDefinitions(RepositoryBeanDefinitionRegistrarSupport.java:85)

  憑直覺解決,我的primary數據庫配置package爲“com.vxx”,數據源二的package配置爲“com.vxx.uxx”,我想還是因爲我把數據源二的包裹在默認數據源的包下,所以導致有些類不知道該選擇哪個數據源了。所以我就把uxx移動到了com層,於是數據源二的package配置爲“com.uxx”,這樣兩個就不會相互干擾了。

  實際上package可以進行多包配置,寫的更細一些把com.vxx下的所有列出來也是可以的。如下

basePackages = {"com.vxx.axx","com.vxx.bxx"}

builder.dataSource(fosunDS).properties(vendorProperties)
       .packages("com.vxx.axx","com.vxx.bxx")

 

  • 配置完遇到的第二個問題
[Vertex-SRM:0.0.0.0:8809] 20:24:33.681 DEBUG 17684 [main] o.s.b.d.LoggingFailureAnalysisReporter Application failed to start due to an exception

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xx.service.PxxMainService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1646)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1205)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1166)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:855)

  我百度了,參看博文:https://www.codetd.com/article/6188038

  裏面有個 component-scan  的配置,這裏剛好項目中有個被註釋了的 @ComponentScan AppRun 這個類上(不然我可能不知道把這個配置加在哪),所以我就重新加上了

@ComponentScan(basePackages = {"com.vxx","com.uxx"})
public class AppRun {

    public static void main(String[] args) {
        SpringApplication.run(AppRun.class, args);
    }

 

  • 項目成功的運行起來,這時候又遇到了一個問題,在有些查詢時候報錯,列名 “createTime”無效

   正常我們是需要在字段上添加註解 @Column(name = "create_time") ,但系統有人默認配置可以將駝峯式映射成_小寫的形式,即 createTime 對應 create_time

這個默認的配置到底在哪呢?遇到這個問題的時候,描述都不好描述,自然沒搜到答案。但實際上,有關這個默認配置的處理,在上述博文中又出現過(動態配置數據源博文),同事提醒了我,我需要反思自己,我其實沒有認真看這些添加東西。

Map<String, String> properties = jpaProperties.getProperties();
//要設置這個屬性,實現 CamelCase -> UnderScore 的轉換
properties.put("hibernate.physical_naming_strategy",
                "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");

 

  至此,項目運行成功,兩個數據庫的操作也完美執行。

 

最後日記

現在是12.23號(第四天)的晚上九點鐘,我在這個問題解決之後,肚子都有些餓了,公司的人都下班了,也本打算下班回家的我還是決定把這個過程給記錄下來。下樓買了桶泡麪喫,這是本週第二頓泡麪(酸辣牛肉麪週一覺得好好喫,今天覺得也不怎麼樣啦),博文竟寫了兩個小時,我相信沒人會把這篇博文看完,包括以後的自己,哈哈哈。疑難雜症解決了,項目的開發內容也一齊做完了。加班一週了,我會因爲我什麼都不會而焦慮,我會因爲遇到問題就不知道怎麼解決而自我懷疑。我想,我總不能一直這麼菜吧。祝願,越來越優秀。

明天是平安夜了,提前祝大家聖誕快樂!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章