我一直知道的MySQL在Linux上有字段名錶名等的大小寫問題,因而爲了不這個問題,選擇了下劃線和全小寫,心說雖然咱用的是JPA,只要使用註解寫清楚表名和字段名是大寫的,不也沒事麼。例如這樣java
實際上證實,想象比搬磚生活豐富的多。親們,我用JPA實現查表操做的時候,Exception跳出來講表不存在,由於表名是全小寫的,我還能怎樣┑( ̄Д  ̄)┍。接下來,折騰纔剛剛開始……不妨看下日誌,心裏異常的沉重spring
2019-09-24 17:31:16.407 ERROR 25864 --- [ XNIO-2 task-1] o.h.engine.jdbc.spi.SqlExceptionHelper : (conn=348) Table '4a.t_assets_mgr' doesn't exist 2019-09-24 17:31:16.420 ERROR 25864 --- [ XNIO-2 task-1] c.s.xxxx.aop.logging.LoggingAspect : Exception in com.xxx.yyyy.service.StaticQuadraa.initLevel() with cause = 'org.hibernate.exception.SQLGrammarException: could not extract ResultSet' and exception = 'could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet' org.springframework.dao.InvalidDataAcce***esourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:242) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527) at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy195.getAllByBusinessName(Unknown Source)
一般狀況下解決這個問題,若是你的數據庫是搭建在windows上面,並且你仍是本身寫玩的,第一步確定是改MySQL的cnf,改爲不區分大小寫,這樣老是能夠的?不過如今都是在docker環境下,這操做,不行了啊,再裝個Oracle又麻煩,怎麼辦呢?既然MySQL那邊解決起來麻煩,咱們在Java這想一想辦法吧。簡單的分析一下過程,瀏覽器點按鈕,發起請求到後臺,Controller接到請求後經過service找到對應的DTO,DTO又經過Spring Data找到Hibernate從而實現的JPA規範,再轉化成SQL語句發送給數據庫執行。所以只要能在發送前把表名改爲大寫就能解決問題了。
那麼這個把表名改爲大寫或者小寫,是在哪裏執行的呢?還記得,JPA對字段有一個轉換,好比a_b會轉換成aB。這個固然不是Java內核實現的,這個是Hibernate的JPA實現作的。具體到代碼,這個東西在spring中是org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy ,是默認使用的。Hibernate實現的這個,就是轉換駝峯規則的功能。我註解裏表名寫的是大寫,可是輸出的sql語句裏是小寫,毫無疑問,這裏有轉換成小寫的代碼。目前,spring data jpa基於Hibernate5,而Hibernate5關於數據庫命名策略的配置與以前版本略有不一樣,其採用implicit-strategy和physical-strategy兩個配置項分別控制命名策略sql
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
這兩個策略仍是有點小小的區別的:docker
這裏提供兩種解決方法:數據庫
能夠在 springboot 項目中配置文件內加上配置行,設置命名爲 無修改命名策略:windows
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
重寫命名策略中改表名爲小寫的方法:瀏覽器
@Component public class MySQLUpperCaseStrategy extends PhysicalNamingStrategyStandardImpl { private static final long serialVersionUID = 1383021413247872469L; @Override public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) { // 將表名所有轉換成大寫 String tableName = name.getText().toUpperCase(); return name.toIdentifier(name.getText()); } }
以後在咱們須要在相關的.yml
文件中使用本身實現的策略springboot
spring.jpa.hibernate.naming:physical-strategy: xx.xx.xx.config.Strategy.MySQLUpperCaseStrategy
這裏我用了方法2,由於在後續的開發中,咱們的開發前輩,對這個數據庫下毒,一共用了駝峯、匈牙利、下劃線,全小寫四種命名風格,簡直前無古人後無來者,念天地之悠悠,願其早日做古而爍今,開局藍buff必被搶,順風必翻盤,鬥地主3456少個7,高鐵吃泡麪少叉子,股票逢買必跌。
在這裏我用了方法2,能夠比較自由的對錶名進行映射修改,而不依賴於他們的命名風格,以至,向先人敬禮!!ide