1.sql的url配置
Spring 循环依赖:简单来说就是自己依赖自己,或者和别的Bean相互依赖。A依赖B,B依赖A,构成一个闭环。
jdbc:mysql://localhost:3306/mybatis?
useSSl=true&
useUnicode=true&
characterEncoding=UTF-8&
serverTimezone=GMT
问题描述
提示The server time zone value '????????' is unrecognized or represents more than one time zone
就是时区错误。
解决问题:
添加serverTimezone=GMT
即可。
2.mybatis查询结果为null时返回不包含
问题描述
mybatis在给map赋值时,如果返回值不是基本数据类型,且返回值为null,就不会处理这个字段,不会将字段的值映射到map中。也就是说返回的map中是没有这个字段的,当结果返回的时候,调用get方法,就直接调用了字段设置的默认值0。
解决问题:
在application.yml配置中添加配置call-setters-on-nulls: true,让mybatis在给map参数映射的时候连null值也一并带过来。
3.循环依赖问题:
Spring 循环依赖:简单来说就是自己依赖自己,或者和别的Bean相互依赖。A依赖B,B依赖A,构成一个闭环。
问题描述
只有单例的Bean才存在循环依赖的情况,原型(Prototype)情况下,Spring会直接抛出异常。原因就是,AB循环依赖,A实例化的时候,发现依赖B,创建B实例,创建B的时候发现需要A,创建A1实例……无限套娃,系统就会垮掉。
方法分析:
单例Bean初始化完成,要经历三步:实例化、属性赋值、初始化
注入就发生在第二步,属性赋值,结合这个过程,Spring 通过三级缓存解决了循环依赖:
一级缓存 : Map<String,Object> singletonObjects,俗称“单例池”“容器”,用于保存实例化、属性赋值(注入)、缓存创建完成单例Bean的地方。
二级缓存 : Map<String,Object> earlySingletonObjects,早期曝光对象,映射Bean的早期引用,也就是说在这个Map里的Bean不是完整的,甚至还不能称之为“Bean”,只是一个Instance用于保存实例化完成的 bean 实例。
三级缓存 : Map<String,ObjectFactory<>> singletonFactories,早期曝光对象工厂,用于保存 bean 创建工厂,以便于后面扩展有机会创建代理对象。
解决过程:
当 A、B 两个类发生循环依赖时:
A实例的初始化过程:
-
创建A实例,实例化的时候把A对象工厂放入三级缓存,表示A开始实例化了。
-
A注入属性时,发现依赖B,此时B还没有被创建出来,所以去实例化B
-
同样,B注入属性时发现依赖A,它就会从缓存里找A对象。依次从一级到三级缓存查询A,从三级缓存通过对象工厂拿到A,发现A虽然不太完善,但是存在,把A放入二级缓存,同时删除三级缓存中的A,此时,B已经实例化并且初始化完成,把B放入一级缓存。
-
接着A属性赋值,从一级缓存拿到实例化且初始化完成的B对象,A对象创建也完成,删除⼆级缓存中的A,同时把A放入一级缓存
-
最后,一级缓存中保存着实例化、初始化都完成的A、B对象
结论:
在Spring中有很多方法可以处理循环依赖。首先要考虑的是重新设计bean,这样就不需要循环依赖:它们通常是可以改进的设计的症状。
但是如果你的项目中绝对需要循环依赖,则可以使用三级缓存。三级缓存的目的是为了在没有循环依赖的情况下,延迟代理对象的创建,使 Bean 的创建符合 Spring 的设计原则。