MyBatis與Spring設置callSettersOnNulls



項目中集成Mybatis與Spring,使用的是Mybatis3.2.7,以及Spring4.0.5,mybatis-spring-1.2.2;
由於項目組成員想要偷懶,將數據從DB中查詢出來時須要將字段映射為Map,而不想封裝成Bean.

默認情況下,Mybatis對Map的解析生成, 假設值(value)為null的話,那么key也不會被增加到map中.
於是對Map遍歷時,key就遍歷不到,由於前端工具的須要,必須有這個key,網上搜索后發現須要設置 callSettersOnNulls 這個屬性.
那就設置唄, 在 sqlSessionFactory 的定義中,指定 configLocation 屬性,指向還有一個文件,例如以下所看到的

文件清單: mybatis-env-setting.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration 
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-config.dtd"> 

<!-- 
	假設內網機器報錯,請使用以下這樣的笨辦法
 -->
<!-- 
<!DOCTYPE configuration
        PUBLIC "-//www.mybatis.org//DTD Config 3.0//EN"
        "E:/bao/tomcat/apache-tomcat-6.0.14/webapps/pmsys/WEB-INF/classes/mybatis/mybatis-3-config.dtd">
 -->

<configuration>
	<settings>
	  <!-- 僅僅設置須要的,其它使用默認值 -->
	  <!-- 開啟緩存,默認就是開啟的,2層開關,須要在Mapper文件里也指定 cache 標簽才會真正使用緩存 -->
	  <setting name="cacheEnabled" value="true"/>
	  <!-- 在null時也調用 setter,適應於返回Map,3.2版本號以上可用 -->
	    <setting name="callSettersOnNulls" value="true"/>
	</settings>
</configuration>

然后使用,一切正常,OK.
過了幾天, 實施項目時出BUG了, 由於是企業內網server,不能訪問 mybatis.org,於是啟動出錯.
【Mybatis 這個渣渣,在啟動時會去獲取並校驗DTD,眼下還不知道在哪里配置讓其不進行校驗.】
網上搜索半天,沒有好的解決的方法, 看到有方法說將dtd下載到本地,然后直接指定路徑,就像上面凝視掉的那部分一樣。

問題也算是攻克了,但是非常土,並且各個機器不一定都有相同的文件夾,這樣的掉渣的方法肯定會遭人詬病的。
於是百度谷歌又搜索了半天,沒找到辦法,根本沒有人提這茬。

於是想着自己翻源代碼看看:
public class SqlSessionFactoryBean 
    implements FactoryBean<SqlSessionFactory>, InitializingBean, 
    ApplicationListener<ApplicationEvent> {

  private static final Log logger = LogFactory.getLog(SqlSessionFactoryBean.class);
  // 這里能夠配置configLocation資源
  private Resource configLocation;

  private Resource[] mapperLocations;

  private DataSource dataSource;

  private TransactionFactory transactionFactory;
  // 這里能夠配置configurationProperties屬性
  private Properties configurationProperties;

  ......

  protected SqlSessionFactory buildSqlSessionFactory() throws IOException {

    Configuration configuration;

    XMLConfigBuilder xmlConfigBuilder = null;
    // 先查找 configLocation 屬性
    if (this.configLocation != null) {
      xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
      configuration = xmlConfigBuilder.getConfiguration();
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");
      }
      // 假設找不到configLocation,就僅僅使用 configurationProperties
      configuration = new Configuration();
      configuration.setVariables(this.configurationProperties);
    }

    ......

看到了  configurationProperties 這個屬性,但是 該怎么設置呢,總算找到了一篇非常靠譜的學習筆記: Spring的Bean之設置Bean值

於是,抄襲之,自己設置了一下相應的屬性

形成的配置文件片段例如以下所看到的:
<!-- myBatis配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="dataSource" />
	
	<!-- 表示在mybatis.mapping包或以下全部文件夾中,以 Mapper.xml結尾全部文件 -->
	<property name="mapperLocations">
		<value>classpath:com/cncounter/dao/oracle/**/*Mapper.xml</value>
		<!-- 
		<list>
			<value>classpath:com/cncounter/dao/oracle/res/*Mapper.xml</value>
			<value>classpath:com/cncounter/dao/oracle/user/*Mapper.xml</value>
		</list>
		 -->
	</property>
	<!-- 
	<property name="configLocation">
		<value>classpath:mybatis/mybatis-env-setting.xml</value>
	</property>
	 -->
	<!--  切換一種方式,不配置configLocation  -->
	<property name="configurationProperties">
		<props>
			<prop key="cacheEnabled">true</prop>
			<prop key="callSettersOnNulls">true</prop>
		</props>
	</property>
</bean>

啟動沒報錯,但是還沒檢驗.應該沒多大問題...

補充: 還是不起作用,於是沒法子了,僅僅好拆開Mybatis的源代碼,找到類 org.apache.ibatis.session.Configuration ,然后,在自己的文件夾下把源代碼拷出來, 自己在test文件夾建一個包,建一個類,和Configuration一模一樣,然后改動 callSettersOnNulls 的默認值為 true,然后找到編譯好的3個class文件(有內部類),替換到mybatis-3.2.7.jar中去,OK,成功解決。

按理說應該是編譯整個mybatis的,但是maven有點坑,眼下還不想這樣做

看了 mybatis高級應用系列一:分頁功能 這篇文章,發覺冤枉 MyBatis了,事實上是 Mybatis-Spring挖下的坑, 校驗的時候不走Mybatis的默認通道, 而是自己解析了相應的XML文件,還要去網上搜索dtd文件,巨坑無比啊.

給了 configurationProperties 這么個選項,卻不使用,真是不好。

附上一篇, 怎樣解決Spring附加組件中dtd的這樣的坑



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM