您的位置:首页 > 编程语言 > Java开发

MyBatis与Spring设置callSettersOnNulls

2016-05-26 11:21 513 查看
项目中集成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

[html] view
plain copy

 





<?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了, 因为是企业内网服务器,不能访问 mybatis.org,于是启动出错.
【Mybatis 这个渣渣,在启动时会去获取并校验DTD,目前还不知道在哪里配置让其不进行校验.】
网上搜索半天,没有好的解决办法, 看到有方法说将dtd下载到本地,然后直接指定路径,就像上面注释掉的那部分一样。

问题也算是解决了,可是很土,而且各个机器不一定都有同样的目录,这种掉渣的方法肯定会遭人诟病的。
于是百度谷歌又搜索了半天,没找到办法,根本没有人提这茬。

于是想着自己翻源码看看:

[java] view
plain copy

 





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值

于是,抄袭之,自己设置了一下相应的属性

形成的配置文件片段如下所示:

[html] view
plain copy

 





<!-- 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 这么个选项,却不使用,真是不好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: