SpringBoot+Mybatis,返回Map的時候,將Map內的Key轉換爲駝峯的命名錶達式

碰見這個問題,是公司的小夥伴跟我說,每次使用mybatis的時候,簡單的連表查詢,用Map接收的時候,都是像DB定義的字段同樣,相似如下 student_name,student_id,沒有轉換爲駝峯,可是又不能由於這一個定義一個javabean來映射數據庫字段集合,這樣,會有無窮無盡的javabean,徹底不是辦法,而後我看了下mybatis-spring-boot的配置文檔http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/,發現有這麼個屬性  html

mybatis.configuration.map-underscore-to-camel-case=true

看着屬性意思,很像是 map 下劃線轉換爲駝峯,而後我天真的覺得,加個這個,就會將Map裏面的key轉換爲駝峯的命名方式,而後我本身測試了一下,發現本身仍是太天真,沒轉過來,該是什麼仍是什麼(內心面是B了狗了)....java

沒辦法,接着找了了一下,發現官方文檔http://www.mybatis.org/mybatis-3/configuration.html#properties,描述過這個的做用 spring

才發現,這個屬性的做用,是做用於javabean的field的,並非map,ㄟ( ▔, ▔ )ㄏ,那沒辦法了,只能本身動手了數據庫

 

 

-------------------------------我是分割線--------------------------------------apache

既然 map-underscore-to-camel-case 不能做用於map,那麼只能本身動手了,而後我就想到了2個解決方案:session

  1. 繼承HashMap,重寫Put函數,將mybatis返回的Map,寫上自定義Map的路徑,自定義的Map,將全部的key內部轉換爲駝峯表達式
  2. 找到mybatis的Handler,經過Handler來找到轉換映射關係的接口定義,繼承或者實現接口,而後走自定義的轉換規則來實現Map映射的駝峯轉換

最終決定,採用第二種,方便之後擴展,以及項目結構mybatis

 

 

首先,我開始找mybatis的configuration裏面的mapUnderscoreToCamelCase屬性調用的地方app

 

有兩個地方調用了,而後咱們看第一個調用的地方,發現名稱是createAutomaticMappings,應該是map的映射字段建立沒跑了,以下代碼,光標顯示的地方,就是調用的地方ide

 

而後咱們在查看屬性傳遞進去後的操做,點進 metaObject.findProperty的實現函數

 

接着在看,objectWrapper.findProperty,發現是個接口,而後咱們須要查看,是對應的哪一個實現,而後我debug發現是 MapWrapper的實現,並無作任何操做,直接返回了name

 

到這裏,我點開了下源碼的目錄結構,發現瞭如下

 

 

內心大概明白怎麼回事了,具體過程應該以下

 

經過接口ObjectWrapper來定義行爲,有默認的一些實現,而後經過工廠ObjectWrapperFactory接口,來建立ObjectWrapper接口,最後來進行對方的自動映射跟包裝,自此,內心已經想到怎麼改動了

 

 

--------------show code-----------------------

 

 

1.首先,咱們先繼承類 MapWrapper,重寫findProperty,經過useCamelCaseMapping來判斷是否開啓使用駝峯

public class CustomWrapper extends MapWrapper{
	
	
	public CustomWrapper(MetaObject metaObject, Map<String, Object> map) {
		super(metaObject, map);
	}
	
	
	@Override
	public String findProperty(String name, boolean useCamelCaseMapping) {
		if(useCamelCaseMapping){
            //CaseFormat是引用的 guava庫,裏面有轉換駝峯的,省得本身重複造輪子,pom添加
            /**
             **         <dependency>
                           <groupId>com.google.guava</groupId>
                           <artifactId>guava</artifactId>
                           <version>24.1-jre</version>
                         </dependency>
             **/
			return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,name);
		}
		return name;
	}
}

 

 2. 而後,咱們在實現接口 ObjectWrapperFactory,經過包裝工廠來建立自定義的包裝類,經過hasWrapperFor判斷參數不爲空,而且類型是Map的時候才使用本身擴展的ObjectWrapper

public class MapWrapperFactory implements ObjectWrapperFactory {
	
	@Override
	public boolean hasWrapperFor(Object object) {
		return object != null && object instanceof Map;
	}
	
	@Override
	public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
		return new CustomWrapper(metaObject,(Map)object);
	}
}

 

 3. 作完以上操做後,咱們須要替換下,之前默認的實現,恰好,mybatis-spring-boot上面有告訴咱們怎麼作,返回一個 ConfigurationCustomizer 的bean,經過匿名內部類實現覆蓋默認的MapWrapper的findProperty函數

@Configuration
public class MybatisConfig {
	
	@Bean
	public ConfigurationCustomizer mybatisConfigurationCustomizer(){
		return new ConfigurationCustomizer() {
			@Override
			public void customize(org.apache.ibatis.session.Configuration configuration) {
				configuration.setObjectWrapperFactory(new MapWrapperFactory());
			}
		};
	}
	
}

 

 

作了以上操做後,咱們就將默認的Map映射,的包裝類,查找property的部分,變成了本身想要的樣子,

最後,咱們在 properties或者yml裏面加上 mybatis.configuration.map-underscore-to-camel-case=true ,畢竟在CustomerWrapper裏面,咱們是經過使用這個來控制是否轉換駝峯的,最後寫個測試用例跑一下,而後會發現,之前db的字段,下劃線已經轉換成駝峯命名了

到這,文章就結束了!

以上,均爲本人測試而得出的結果,可能會有出入,或者錯誤,歡迎指正

歡迎轉載,請註明出處跟做者,謝謝!

相關文章
相關標籤/搜索