mybatis中resultMap配置细则

article/2025/10/7 8:06:40

关注公众号【江南一点雨】,专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!


resultMap算是mybatis映射器中最复杂的一个节点了,能够配置的属性较多,我们在mybatis映射器配置细则这篇博客中已经简单介绍过resultMap的配置了,当时我们介绍了resultMap中的id和result节点,那么在resultMap中除了这两个之外,还有其他节点,今天我们就来详细说说resultMap中的这些节点。
如果小伙伴对mybatis尚不了解,建议先翻看博主前面几篇博客了解一下,否则本文你可能难以理解,老司机请略过。
#概览
先来看看resultMap中都有那些属性:

<resultMap><constructor><idArg/><arg/></constructor><id/><result/><association property=""/><collection property=""/><discriminator javaType=""><case value=""></case></discriminator></resultMap>

我们看到,resultMap中一共有六种不同的节点,除了id和result我们在mybatis映射器配置细则这篇博客中已经介绍过了之外,还剩三种,剩下的四个本文我们就来一个一个看一下。
#constructor
constructor主要是用来配置构造方法,默认情况下mybatis会调用实体类的无参构造方法创建一个实体类,然后再给各个属性赋值,但是有的时候我们可能为实体类生成了有参的构造方法,并且也没有给该实体类生成无参的构造方法,这个时候如果不做特殊配置,resultMap在生成实体类的时候就会报错,因为它没有找到无参构造方法。这个时候mybatis会报如下错误:
这里写图片描述
那么解决方式很简单,就是在constructor节点中进行简单配置,假设我现在User实体类的构造方法如下:

public User(Long id, String username, String password, String address) {this.id = id;this.username = username;this.password = password;this.address = address;}

那么我在resultMap中配置constructor节点,如下:

<resultMap id="userResultMap" type="org.sang.bean.User"><constructor><idArg column="id" javaType="long"/><arg column="username" javaType="string"/><arg column="password" javaType="string"/><arg column="address" javaType="string"/></constructor></resultMap>

在constructor中指定相应的参数,这样resultMap在构造实体类的时候就会按照这里的指定的参数寻找相应的构造方法去完成了。
#association
association是mybatis支持级联的一部分,我们知道在级联中有一对一、一对多、多对多等关系,association主要是用来解决一对一关系的,假设我现在有两张表,一张表示省份,一张表示省份的别名,假设一个省只有一个别名(实际上有的省份有两个别名),我们来看一下如下两张表:
1.省份表:
这里写图片描述
说明一下最后一个area字段表示该省是属于南方还是北方。
2.别名表:
这里写图片描述
别名表中pid表示省份的id,假设我现在有一个实体类,Province,该类有两个属性,一个叫做name表示省份的名字,一个叫做alias表示省份的别名,那么我在查询的时候可以通过association来实现这种一对一级联,实现方式如下:
##创建Alias实体类

public class Alias {private Long id;private String name;//省略getter/setter
}

##创建Province实体类

public class Province {private Long id;private String name;private Alias alias;//省略getter/setter
}

##创建AliasMapper

public interface AliasMapper {Alias findAliasByPid(Long id);
}

这里就提供一个方法,根据省份的id找到省份的别名。
##创建aliasMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.AliasMapper"><select id="findAliasByPid" parameterType="long" resultType="org.sang.bean.Alias">SELECT * FROM alias WHERE pid=#{id}</select>
</mapper>

##创建ProvinceMapper

public interface ProvinceMapper {List<Province> getProvince();
}

##创建provinceMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.ProvinceMapper"><resultMap id="provinceResultMapper" type="org.sang.bean.Province"><id column="id" property="id"/><association property="alias" column="id" select="org.sang.db.AliasMapper.findAliasByPid"/></resultMap><select id="getProvince" resultMap="provinceResultMapper">SELECT * FROM province</select></mapper>

小伙伴们注意这里的resultMap,我们在resultMap中指定了association节点,association节点中的select属性表示要执行的方法,该方法实际上指向了一条SQL语句(就是我们在aliasMapper.xml中配置的那条SQL语句),column表示给方法传入的参数的字段,我们这里要传入省份的id,所以column为id,property表示select查询的结果要赋值给谁,我们这里当然是赋值给Province的alias属性。
##在mybatis-conf.xml中配置mapper

<mappers><mapper resource="provinceMapper.xml"/><mapper resource="aliasMapper.xml"/></mappers>

##测试

    @Testpublic void test7() {SqlSession sqlSession = null;try {sqlSession = DBUtils.openSqlSession();ProvinceMapper pm = sqlSession.getMapper(ProvinceMapper.class);List<Province> list = pm.getProvince();for (Province province : list) {System.out.println(province);}sqlSession.commit();} catch (Exception e) {e.printStackTrace();sqlSession.rollback();} finally {if (sqlSession != null) {sqlSession.close();}}}

测试结果:
这里写图片描述
OK,这就是简单的一对一级联的使用。

#collection
collection是用来解决一对多级联的,还是上面那个例子,每个省份下面都会有很多城市,于是,我来创建一张城市表,如下:
这里写图片描述
城市表中有一个pid字段,该字段表示这个城市是属于哪个省份的,OK,假设我现在Province实体类中多了一个属性叫做cities,这个cities属性的数据类型是一个List集合,这个集合中放的所有的数据就是这个省份的,我希望查询结束之后这个属性的值就会被自动填充,OK,那么在上面那个案例的基础上,我们来看看这个要怎么实现。
##为Province类添加属性
新的Province类变成下面这个样子:

public class Province {private Long id;private String name;private Alias alias;private List<City> cities;//省略getter/setter
}

##创建City实体类

public class City {private Long id;private Long pid;private String name;//省略getter/setter
}

##创建CityMapper

public interface CityMapper {List<City> findCityByPid(Long id);
}

CityMapper中就提供一个方法,那就是根据省份的id来查找到相应的城市。
##创建cityMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.CityMapper"><select id="findCityByPid" parameterType="long" resultType="org.sang.bean.City">SELECT * FROM city WHERE pid=#{id}</select>
</mapper>

##在mybatis-conf.xml中配置mapper

<mappers><mapper resource="provinceMapper.xml"/><mapper resource="aliasMapper.xml"/><mapper resource="cityMapper.xml"/></mappers>

##修改provinceMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.ProvinceMapper"><resultMap id="provinceResultMapper" type="org.sang.bean.Province"><id column="id" property="id"/><association property="alias" column="id" select="org.sang.db.AliasMapper.findAliasByPid"/><collection property="cities" column="id" select="org.sang.db.CityMapper.findCityByPid"/></resultMap><select id="getProvince" resultMap="provinceResultMapper">SELECT * FROM province</select></mapper>

多了一个collection节点,节点中属性的含义和association都是一样的,我这里不再赘述。OK,如此之后,我们就可以来测试了。
##测试
测试代码(和上面association的测试代码是一样的):

    @Testpublic void test7() {SqlSession sqlSession = null;try {sqlSession = DBUtils.openSqlSession();ProvinceMapper pm = sqlSession.getMapper(ProvinceMapper.class);List<Province> list = pm.getProvince();for (Province province : list) {System.out.println(province);}sqlSession.commit();} catch (Exception e) {e.printStackTrace();sqlSession.rollback();} finally {if (sqlSession != null) {sqlSession.close();}}}

测试结果:
这里写图片描述
OK,Province的cities属性已经被顺利赋上值了。
#discriminator
discriminator既不是一对多也不是一对一,这个我们称之为鉴别器级联,使用它我们可以在不同的条件下执行不同的查询匹配不同的实体类,还是以上文的例子为例,不同的省份分别属于南北方,南北方的人有不同的饮食习惯,北方人吃面、南方人吃米饭,据此,我来新创建三个类,分别是Food、Rice、Noodle三个类,其中Food是Rice和Noodle的父类,将两者之间的一些共性抽取出来,这三个类如下:

public class Food {protected Long id;protected String name;//省略getter/setter
}
public class Noodle extends Food{//每天吃几次private int price;//省略getter/setter
}
public class Rice extends Food {//烹饪方法private String way;//省略getter/setter}

然后我在数据库中再分别创建两张表,分别是rice表和noodle表,如下:
这里写图片描述
然后我现在现在再修改我的Province实体类,如下:

public class Province {private Long id;private String name;private Alias alias;private List<City> cities;private List<Food> foods;//省略getter/setter
}

这次多了一个foods属性,这个属性是这样,当我在数据库中查询的时候,如果查到这个省份是北方省份,那么就自动去查询noodle表,将查到的结果赋值给foods属性,如果这个省份是南方省份,那么就自动去查询rice表,将查到的结果赋值给foods属性,这种要根据查询结果动态匹配查询语句的需求,我们就可以通过discriminator来实现。OK,接下来我们为Rice和Noodle分别创建Mapper,并在mybatis-conf.xml中注册mapper,结果如下:

public interface RiceMapper {List<Rice> findRiceByArea();
}
public interface NoodleMapper {List<Noodle> findNoodleByArea();
}

noodleMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.NoodleMapper"><select id="findNoodleByArea" resultType="org.sang.bean.Noodle">SELECT * FROM noodle</select>
</mapper>

riceMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.RiceMapper"><select id="findRiceByArea" resultType="org.sang.bean.Rice">SELECT * FROM rice</select>
</mapper>

mybaits-conf.xml

<mappers><mapper resource="provinceMapper.xml"/><mapper resource="aliasMapper.xml"/><mapper resource="cityMapper.xml"/><mapper resource="riceMapper.xml"/><mapper resource="noodleMapper.xml"/></mappers>

OK ,做完这些之后接下来我们就可以来稍微的完善下provinceMapper.xml了,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.ProvinceMapper"><resultMap id="provinceResultMapper" type="org.sang.bean.Province"><id column="id" property="id"/><association property="alias" column="id" select="org.sang.db.AliasMapper.findAliasByPid"/><collection property="cities" column="id" select="org.sang.db.CityMapper.findCityByPid"/><discriminator javaType="int" column="area"><case value="1" resultMap="noodleResultMap"></case><case value="2" resultMap="riceResultMap"></case></discriminator></resultMap><resultMap id="noodleResultMap" type="org.sang.bean.Province" extends="provinceResultMapper"><collection property="foods" column="area" select="org.sang.db.NoodleMapper.findNoodleByArea"/></resultMap><resultMap id="riceResultMap" type="org.sang.bean.Province" extends="provinceResultMapper"><collection property="foods" column="area" select="org.sang.db.RiceMapper.findRiceByArea"/></resultMap><select id="getProvince" resultMap="provinceResultMapper">SELECT * FROM province</select></mapper>

小伙伴们注意,我们在这里添加了discriminator节点,该节点有点类似于switch语句,column表示用哪个值参与比较,我们这里使用area字段进行比较,当area为0时(即北方省份)我们使用的resultMap为noodleResultMap,当area为1时(即南方省份)我们使用的resultMap为riceResultMap,然后我们在下面再分别定义riceResultMap和noodleResultMap,但是注意这两个里边返回值类型都是Province,也都是继承自provinceResultMapper,这里的继承和我们Java中面向对象的继承差不多,父类有的子类继承之后也都自动具备了。这样做时候,我们再来运行刚才的测试代码,结果如下:
这里写图片描述

和我们想的基本一致。

#延迟加载问题
按照上文我们介绍的方式,每次查询省份的时候都会去查询别名食物等表,有的时候我们可能并不需要这些数据但是却无可避免的要调用这个方法,那么在mybatis中,针对这个问题也提出了相应的解决方案,那就是延迟加载,延迟加载就是当我需要调用这条数据的时候mybatis再去数据库中查询这条数据,比如Province的foods属性,当我调用Province的getFoods()方法来获取这条数据的时候系统再去执行相应的查询操作。OK,针对这个需求mybatis给我们提供了两种不同的方式,一种是在mybatis的配置文件中进行配置,还有一种是针对不同的查询进行单独配置,我们接下来就来看一下这两种不同的配置方式。
##在mybatis的配置文件中进行配置
这种配置有点类似于全局配置,配置成功之后,所有的查询操作都开启了延迟加载。配置方式如下:

<settings><setting name="lazyLoadingEnabled" value="true"/><setting name="aggressiveLazyLoading" value="false"/></settings>

OK,直接在mybatis-conf.xml中添加如上配置即可。那么这里涉及到两个属性,含义不同,我们来分别看一下:

1.lazyLoadingEnabled表示是否开启延迟加载,默认为false表示没有开启,true表示开启延迟加载。
2.aggressiveLazyLoading表示延迟加载的时候内容是按照层级来延迟加载还是按照需求来延迟加载,默认为true表示按照层级来延迟加载,false表示按照需求来延迟加载。以我们上文查询食物的需求为例,去查询rice表或者noodle表是属于同一级的,但是在我查询到陕西省的时候,这个时候只需要去查询noodle表就可以了,当我查询到广东省的时候再去查询rice表,但是如果aggressiveLazyLoading为true的话,即使我只查询到陕西省,系统也会去把rice和noodle都查一遍,因为它俩属于同一级,而如果aggressiveLazyLoading为false的话,那么当我查询到陕西省的时候,系统就只查询noodle表,当我查询到广东省的时候系统才去查询rice表。

OK,这样配置之后,我们再来看看查询日志:
这里写图片描述

和我们想的一致。
##在针对不同的查询进行配置
OK,上面这种配置算是一种全局配置,如果我们想针对某一条查询开启延迟加载该怎么做呢?比如针对省份别名的查询我想即时加载,而针对城市的查询我想延迟加载该怎么办呢?很简单,在association和collection中配置fetchType属性就可以啦。如上需求,如下配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.db.ProvinceMapper"><resultMap id="provinceResultMapper" type="org.sang.bean.Province"><id column="id" property="id"/><association property="alias" column="id" select="org.sang.db.AliasMapper.findAliasByPid" fetchType="eager"/><collection property="cities" column="id" select="org.sang.db.CityMapper.findCityByPid" fetchType="lazy"/><discriminator javaType="int" column="area"><case value="1" resultMap="noodleResultMap"></case><case value="2" resultMap="riceResultMap"></case></discriminator></resultMap><resultMap id="noodleResultMap" type="org.sang.bean.Province" extends="provinceResultMapper"><collection property="foods" column="area" select="org.sang.db.NoodleMapper.findNoodleByArea"/></resultMap><resultMap id="riceResultMap" type="org.sang.bean.Province" extends="provinceResultMapper"><collection property="foods" column="area" select="org.sang.db.RiceMapper.findRiceByArea"/></resultMap><select id="getProvince" resultMap="provinceResultMapper">SELECT * FROM province</select></mapper>

eager表示即时加载,lazy表示延迟加载。OK,做了如上配置之后,我们再来看看查询日志:
这里写图片描述

和我们想的基本一致。

#小插曲
关于resultMap我们就说上面那么多。最后我们再来稍微说一下mapper中的sql元素吧。sql元素有点像变量的定义,如果一个表的字段特别多,我们总是写select XXX,XXX,XXX from X总是很麻烦,我们可能希望将一些通用的东西提取成变量然后单独引用,那么这个提取方式也很简单,那就是sql变量,如下:

<sql id="selectAll">SELECT * FROM user</sql>

这里是将整个查询语句封装,然后在select中引用即可,如下:

<select id="getUser2" resultType="user"><include refid="selectAll"/></select>

也可以只封装一部分查询语句,如下:

<sql id="selectAll3">id,username,address,password</sql>

引用方式如下:

<select id="getUser3" resultType="user">SELECT<include refid="selectAll3"/> FROM user</select>

还可以在封装的时候使用一些变量,如下:

<sql id="selectAll4">${prefix}.id,${prefix}.username,${prefix}.address</sql>

注意变量引用方式是$符号哦,不是#,引用方式如下:

<select id="getUser4" resultType="user" parameterType="string">SELECT<include refid="selectAll4"><property name="prefix" value="u"/></include> FROM user u</select>

在property中设置prefix的值。

OK,以上。

本文案例下载:
本文案例GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test27-mybatis7。

参考资料:
《深入浅出MyBatis 技术原理与实战》第四章


http://chatgpt.dhexx.cn/article/t55uItkm.shtml

相关文章

深度解析resultMap标签

一般来说&#xff0c;一张表对应一份mapper映射文件&#xff0c;但部分属性在数据库中的存储并非直接存储其内容&#xff0c;而是存储其唯一标识&#xff0c;比如id&#xff0c;如下表中的员工政治面貌、部门、职级、岗位均是通过各个分表的id进行维护&#xff1a; 因此&#x…

ResultType和ResultMap的区别

ResultType和ResultMap都是执行查询语句时返回的结果集 ResultType ResultType相对与ResultMap而言更简单一点。只有满足ORM&#xff08;Object Relational Mapping&#xff0c;对象关系映射&#xff09;时&#xff0c;即数据库表中的字段名和实体类中的属性完全一致时&#x…

resultMap的用法以及关联结果集映射

resultType resultType可以把查询结果封装到pojo类型中&#xff0c;但必须pojo类的属性名和查询到的数据库表的字段名一致。 如果sql查询到的字段与pojo的属性名不一致&#xff0c;则需要使用resultMap将字段名和属性名对应起来&#xff0c;进行手动配置封装&#xff0c;将结…

[MyBatis]-resultMap结果映射集详解

resultMap结果映射集详解 resultmap是mybatis中最复杂的元素之一&#xff0c;它描述如何从结果集中加载对象&#xff0c;主要作用是定义映射规则、级联的更新、定制类型转化器。 resultmap构成元素 元素子元素作用constructoridArg 、arg用于配置构造器方法id将结果集标记为id…

MyBatis中ResultMap详解

简介&#xff1a; MyBatis的每一个查询映射的返回类型都是ResultMap&#xff0c;只是当我们提供的返回类型属性是resultType的时候&#xff0c;MyBatis会自动的给我们把对应的值赋给resultType所指定对象的属性&#xff0c;而当我们提供的返回类型是resultMap的时候&#xff0…

MyBatis多表查询resultMap设定

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Result Maps 是什么 ResultMap 属性 一、Java数据访问接口 二、XML实现 1、*分步查询 延迟加载 三、Test 1.读入数据 总结 Result Maps 是什么 resultMap 元素是 M…

JS字符串替换指定字符

碰到一个后端数据同步过来的xml文本段&#xff0c;内容里写死的宽度 在1920*1080的分辨率屏幕上&#xff0c;显示有问题&#xff0c;由于数据量太多&#xff0c;前端单独拿数据再处理一遍 RegExp方法&#xff1a; function replaceAll(str, find, replace) {return str.repla…

shell内置字符串替换

shell变量赋值语法&#xff1a; 使用规则解释单引号所见即所得&#xff0c;即输出时会将单引号内的所有內容都原样输出&#xff0c;或者描述为单引号里面看到的是什么就会输出什么&#xff0c;这称为强引用双引号 (默认)输出双引号内的所有内容&#xff1b;如果内容中有命令(…

python字符串替换

str.replace(old, new[, max]) 参数 old – 将被替换的子字符串。 new – 新字符串&#xff0c;用于替换old子字符串。 max – 可选字符串, 替换不超过 max 次 返回值 返回字符串中的 old&#xff08;旧字符串&#xff09; 替换成 new(新字符串)后生成的新字符串&#xff0c;如…

C++ 字符串替换

好久没有更新了&#xff0c;最近有点忙&#xff0c;今天抽点时间给大家水 写一篇关于替换字符串字符的文章 替换函数 string类型的字符串可以用swap函数来替换字符&#xff0c;例如&#xff1a; 冒泡排序 #include <bits/stdc.h> using namespace std;int main () {i…

Python字符串替换方法replace

字符串替换方法replace str1 .replace(old_str&#xff0c;new_str&#xff0c;count)字符串的替换&#xff0c;将str1中的 old_str 替换成new_str old_str:将要被替换的字符串 new_str:新的字符串&#xff0c;替换成的字符串# count:替换的次数,默认是全部替换 返回值:得到一个…

Java字符串替换的方法

java中字符串替换方法主要有三种&#xff0c;分别是replace()、replaceAll()和replaceFirst()&#xff0c;这三种方法可以在三种不同情况应用&#xff0c;下面就由我来具体说明这三种方法的应用情况吧。 replace() replace的参数是char和CharSequence&#xff0c;即可以支持字…

sed 字符串替换

1. sed替换的基本语法为: sed s/原字符串/替换字符串/ 单引号里面,s表示替换,三根斜线中间是替换的样式,特殊字符需要使用反斜线”\”进行转义。 2. 单引号” ‘ ’”是没有办法用反斜线”\”转义的,这时候只要把命令中的单引号改为双引号就行了,格式如下&#xff1a; # 要…

字符串的替换

一、字符串“打劫&#xff01;我有枪”&#xff0c;“枪”是敏感词汇&#xff0c;替换为“*”&#xff0c;并输出打印 二、字符串“北京欢迎你”&#xff0c;替换字符为“郑州欢迎你们”&#xff0c;并输出打印 package work.twelve;/* 一、字符串“打劫&#xff01;我有枪”…

两种字符串替换的方法

1.语法&#xff1a; public String replace(CharSequence target,CharSquence replacement) 注&#xff1a;旧字符换成新字符 示例&#xff1a;店小二在菜单上写下一个馒头一文&#xff0c;“一个”二字容易被他人添上一笔变成“十个”&#xff0c;于是决定把“一”替换成汉字…

7-8 字符串替换 (15 分)

7-8 字符串替换 &#xff08;15 分&#xff09; 本题要求编写程序&#xff0c;将给定字符串中的大写英文字母按以下对应规则替换&#xff1a; 输入格式&#xff1a; 输入在一行中给出一个不超过80个字符、并以回车结束的字符串。 输出格式&#xff1a; 输出在一行中给出替…

全网最全Spring面试题之高级篇整理总结(共25题,附超详细解答)

1、什么是 Spring 框架&#xff1f;Spring 框架有哪些主要模块&#xff1f; Spring 框架是一个为 Java 应用程序的开发提供了综合、广泛的基础性支持的 Java 平台。Spring 帮助开发者解决了开发中基础性的问题&#xff0c;使得开发人员可以专注于应用程序的开发。 Spring 框架本…

spring常见面试题(2023最新)

目录 前言1.spring是什么2.spring的设计核心是什么3.IOC和AOP面试题4.spring的优点和缺点5.spring中bean的作用域6.spring中bean的注入方式7.BeanFactory 和 ApplicationContext有什么区别&#xff1f;8.循环依赖的情况&#xff0c;怎么解决&#xff1f;9.spring中单例Bean是线…

spring面试题及答案

关注公众号&#xff0c;获取更多面试题及答案。 69道Spring面试题 1.什么是spring? Spring是个java企业级应用的开源开发框架。Spring主要用来开发Java应用&#xff0c;但是有些扩展是针对构建J2EE平台的web应用。Spring框架目标是简化Java企业级应用开发&#xff0c;并通过…

【2022版】Spring面试题整理(含答案解析)

1、不同版本的 Spring Framework 有哪些主要功能&#xff1f; 2、什么是 Spring Framework&#xff1f; Spring 是一个开源应用框架&#xff0c;旨在降低应用程序开发的复杂度。它是轻量级、松散耦合的。它具有分层体系结构&#xff0c;允许用户选择组件&#xff0c;同时还为 …