zoukankan      html  css  js  c++  java
  • 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的这样的坑


  • 相关阅读:
    第一个爬虫和测试
    数学规律
    自定义手绘
    tqqqy的成绩表
    Linux常用命令-netstat
    文档查看命令 cat more less tail head
    Linux三剑客-常用命令
    IO多路复用模型
    redis 的线程模型
    为什么需要缓存?
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4049728.html
Copyright © 2011-2022 走看看