MyBatis与Spring设置callSettersOnNulls

简介: 项目中集成Mybatis与Spring,使用的是Mybatis3.2.7,以及Spring4.0.5,mybatis-spring-1.2.2;因为项目组成员想要偷懒,将数据从DB中查询出来时需要将字段映射为Map,而不想封装成Bean.

项目中集成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了, 因为是企业内网服务器,不能访问 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的这种坑


目录
相关文章
|
1月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
216 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
2月前
|
Java 数据库连接 数据库
spring复习05,spring整合mybatis,声明式事务
这篇文章详细介绍了如何在Spring框架中整合MyBatis以及如何配置声明式事务。主要内容包括:在Maven项目中添加依赖、创建实体类和Mapper接口、配置MyBatis核心配置文件和映射文件、配置数据源、创建sqlSessionFactory和sqlSessionTemplate、实现Mapper接口、配置声明式事务以及测试使用。此外,还解释了声明式事务的传播行为、隔离级别、只读提示和事务超时期间等概念。
spring复习05,spring整合mybatis,声明式事务
|
2月前
|
Java Spring
spring多线程实现+合理设置最大线程数和核心线程数
本文介绍了手动设置线程池时的最大线程数和核心线程数配置方法,建议根据CPU核数及程序类型(CPU密集型或IO密集型)来合理设定。对于IO密集型,核心线程数设为CPU核数的两倍;CPU密集型则设为CPU核数加一。此外,还讨论了`maxPoolSize`、`keepAliveTime`、`allowCoreThreadTimeout`和`queueCapacity`等参数的设置策略,以确保线程池高效稳定运行。
194 10
spring多线程实现+合理设置最大线程数和核心线程数
|
23天前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
35 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
2月前
|
Java 数据库连接 数据库
SpringBoot 整合jdbc和mybatis
本文详细介绍了如何在SpringBoot项目中整合JDBC与MyBatis,并提供了具体的配置步骤和示例代码。首先,通过创建用户实体类和数据库表来准备基础环境;接着,配置Maven依赖、数据库连接及属性;最后,分别展示了JDBC与MyBatis的集成方法及其基本操作,包括增删查改等功能的实现。适合初学者快速入门。
SpringBoot 整合jdbc和mybatis
|
27天前
|
存储 Java API
简单两步,Spring Boot 写死的定时任务也能动态设置:技术干货分享
【10月更文挑战第4天】在Spring Boot开发中,定时任务通常通过@Scheduled注解来实现,这种方式简单直接,但存在一个显著的限制:任务的执行时间或频率在编译时就已经确定,无法在运行时动态调整。然而,在实际工作中,我们往往需要根据业务需求或外部条件的变化来动态调整定时任务的执行计划。本文将分享一个简单两步的解决方案,让你的Spring Boot应用中的定时任务也能动态设置,从而满足更灵活的业务需求。
59 4
|
25天前
|
Java 数据库连接 API
springBoot:后端解决跨域&Mybatis-Plus&SwaggerUI&代码生成器 (四)
本文介绍了后端解决跨域问题的方法及Mybatis-Plus的配置与使用。首先通过创建`CorsConfig`类并设置相关参数来实现跨域请求处理。接着,详细描述了如何引入Mybatis-Plus插件,包括配置`MybatisPlusConfig`类、定义Mapper接口以及Service层。此外,还展示了如何配置分页查询功能,并引入SwaggerUI进行API文档生成。最后,提供了代码生成器的配置示例,帮助快速生成项目所需的基础代码。
|
2月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
1月前
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
35 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
1月前
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
101 0
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码