附录_Spring&Mybatis面试题汇总

Spring、SpringMVC面试题汇总

Spring框架概述(介绍)?

Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java的配置。

你都了解哪些 SpringFramework的组件,谈谈他们的作用?

> Spring Core:核心类库,提供IOC服务;
> Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);
> Spring AOP:AOP服务;
> Spring DAO:对JDBC的抽象,简化了数据访问异常的处理;
> Spring ORM:对现有的ORM框架的支持;
> Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传;
> Spring MVC:提供面向Web应用的Model-View-Controller实现。

使用Spring框架能带来哪些好处?

> (1)spring属于低侵入式设计,代码的污染极低;
> (2)spring的DI机制将对象之间的依赖关系交由框架处理,减低组件的耦合性;
> (3)Spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用。
> (4)spring对于主流的应用框架提供了集成支持。

Spring有哪些配置方式?

常见的配置方式有三种:
基于XML的配置、

基于注解的配置(@Component、@Repository、@Controller)、

基于Java类+配置注解的方式(@Configuration @Bean)。

什么是基于注解的容器配置,如何在Spring中启动注解装配?

在Spring的配置文件中 定义注解扫描的范围
<context:component-scan base-package="com.itcast" />

这样 在com.itcast包下的所有标注了 @Component、@Repository、@Controller注解的类,会被注册到容器中

Spring框架中使用到的设计模式?

工厂模式:  Spring中的FactoryBean就是典型的工厂方法模式。使用工厂模式创建对象的实例
单例模式:在Spring配置文件中定义的Bean默认为单例模式

模板方法:用来解决代码重复的问题,比如我们常使用的RestTemplate、JmsTemplate、JpaTemplate都是基于模板方法

代理模式: AOP的底层实现就是基于JDK动态代理 及 CGLIB动态代理

观察者模式:Spring中Observer模式常用的地方是listener的实现。如ApplicationListener。

适配器模式:AOP的方法拦截器中

策略模式:Spring中在实例化对象的时候用到Strategy模式

什么是Spring IOC容器?

> (1)IOC就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源。
> (2)最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。
> (3)Spring的IOC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。

什么是依赖注入 ?

DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。 

DI依赖注入的几种方式?

构造器注入、setter方法注入、根据注解注入

IOC和DI有什么区别

IOC偏向一种思想,对象的创建权,由程序交给了IOC容器,所以叫控制反转,而DI强调的是容器要负责创建对象,但对象在创建时可能需要赋值一些属性,或者依赖其他对象,定义容器内对象时需要定义好这些关系,这样容器在创建对象时就会根据这些关系帮我们自定的设置好属性 或 依赖的对象。 这两实际上都是在介绍容器的功能,只是从不同的方面去解释容器而已。

Spring中有常用的IOC容器,及他们的实现类

> IOC容器的顶级接口 BeanFactory , 仅提供了最基本的容器方法
> ApplicationContext接口 则扩展了BeanFactory,提供了很多功能,使我们常用的容器
> BeanFacotry的实现类 XmlBeanFactory
> ApplicationContext的实现类:
> **ClassPathXmlApplicationContext**:可以加载类路径下的配置文件,实现容器的实例化。
> **FileSystemXmlApplicationContext**:可以加载磁盘任意路径下的配置文件,实现容器的实例化。(必须有访问权限)
> **AnnotationConfigApplicationContext  **:扫描配置注解,根据注解配置实现容器的实例化。

配置Bean对象的常用属性?

> **id**标签是bean的唯一标识,IoC容器中bean的id标签不能重复,否则报错。
> **name**是bean的别名,可以定义多个 
> **class属性**是bean常用属性,为bean的全限定类名,指向classpath下类定义所在位置
> **factory-method**属性factory-method工厂方法属性,通过该属性,我们可以调用一个指定的静态工厂方法,创建bean实例。
> **scope属性** bean的作用范围 
> **init-method和destory-method属性 ** Bean的初始化和销毁时执行的方法
> **autowire属性** 表示bean的自动装配方式 可选值: no:默认,不进行自动装配  .byName .byType 

SpringBean对象的作用域?(scope属性的值)

> **singleton**:表示整个IOC容器共享一个Bean,也就是说每次说每次通过getBean获取的bean都是同一个。
> **prototype**:每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。
> **request**:每次HTTP请求将会生成各自的bean实例
> **session**:每次会话请求对应一个bean实例
> **global-session**:全局作用域
> singleton和prototype经常使用,其他的很少使用。

SpringBean对象的生命周期?

> **(1)实例化Bean:**

> 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。

> **(2)设置对象属性(依赖注入):**

> 实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。


> **(3)处理Aware接口:**

> 接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:
> ①如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的就是Spring配置文件中Bean的id值;
> ②如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。
> ③如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;

> **(4)BeanPostProcessor:**

> 如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)方法。

> **(5)InitializingBean 与 init-method:**

> 如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。

> **(6)如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;**

> 以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。


> **(7)DisposableBean:**
> 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;

> **(8)destroy-method:**
> 最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

SpringBean对象是否线程安全?Spring如何处理线程并发问题?

Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

Spring的常用注解?

> @ComponentScan  组件扫描, 会扫描指定包下的 @Component @Controller @Service @Repository
> @Controller    标注当前类为容器的对象,代表控制组件
> @Service       标注当前类为容器的对象,代表服务组件
> @Repository    标注当前类为容器的对象,代表持久组件
> @Component     标注当前类为容器的对象,代表组件

> @Autowired    自动装配注解  默认按类型装配 
> @Transactional   事务注解
> @Value     将配置文件中的值,注入到指定字段
> @Bean      配置bean对象   <bean>标签作用一致
> @Configuration 标注当前的java类是一个配置类


PS:@Controller @Service @Component @Repository的区别
- @Component spring基础的注解,被spring管理的组件或bean
- @Repository 用于持久层,数据库访问层
- @Service 用于服务层,处理业务逻辑
- @Controller 用于呈现层,(spring-mvc)

@Autowired和@Resource注解的区别?

> 1、 @Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。

> 2、 @Autowired默认按类型装配(这个注解是属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以搭配@Qualifier注解进行使用

> 3、@Resource(这个注解属于J2EE的),默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

springMVC常用注解

> @RequestMapping 指定请求资源路径**

> @ResponseBody 注解表示将该方法的返回值 直接返回到客户端,一般我们返回的都是 json**

> @RequestBody** 接收前台 json参数
> @RequestParam 接收前台表单参数 key = value 形式参数 ? a=1 & b=2
> @PathVariable 获取路径参数的** http:ip:port/user/111 

> @RestController  相当于 @ResponseBody 和 @Controller的合体
> @ControllerAdvice  controller的增强注解,用于统一处理功能:如统一异常处理
> @ExceptionHandler  异常处理

> @CookieValue 指定cookie中的参数
> @RequestHeader 指定请求消息头中的参数

什么是Spring的内部Bean

当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,为了定义inner bean,在Spring 的 基于XML的 配置元数据中,可以在 <property/>或 <constructor-arg/> 元素内使用<bean/> 元素,内部bean通常是匿名的,它们的Scope一般是prototype。

IOC容器构建对象的几种方式?

> 1)调用无参数构造器
> 2)带参数构造器
> 3)工厂创建对象
>   工厂类:静态方法创建对象
>   工厂类:非静态方法创建对象

了解Spring的源码吗?IOC容器的初始化流程是怎样的? (简述Spring IOC的实现机制)

结合课件总结话术

什么叫延迟加载

默认情况下,scope位singlton的Spring Bean对象,在容器初始化完毕后会直接加载的,如果需要改成什么时候用什么时候加载,可以修改配置中的 init-lazy属性位true,这样就设置了延迟加载

Spring Bean 怎样解决循环依赖的问题

Spring Bean的Scope为Singleton时,循环依赖问题可以通过三级缓存来解决。
另外不使用构造函数传参的方式,可以改为属性传参 或者 @Autowired注解的方式

项目中使用AOP的场景?

比较常用的 事务、权限、异常、  用户行为日志、  性能监控、缓存等等

用户行为日志: 
某时  张三  添加一条用户信息  操作耗时:  电脑IP: 
某时  张三  删除一条用户信息  操作耗时:  电脑IP: 
某时  张三  修改一条用户信息  操作耗时:  电脑IP: 

介绍基本概念
AOP:面向切面编程

简单理解-->
可以让我们把分散到项目中的各种通用性功能抽取出来,
统一在切面类中实现:

举例-->
比如:  通用的异常、权限、日志、事务等等的处理
好处-->
这样可以通过面向切面实现非常好的解耦和 以及统一管理我们的代码


说清楚基本用法

定义切面类   我们使用注解的方式  @Aspect  @Component

定义切入点表达式   可以通过 扫描包的方式  也 可以通过指定注解的方式

定义通知:  通知分5种  
我们通常使用环绕通知

说清楚底层原理

AOP的底层的工作原理 就是使用动态代理对目标业务进行增强,而动态代理使用的就是JDK 和 CGLIB两种动态代理

使用AOP进行面向切面开发的步骤?(如何实现)

SpringAOP 的底层实现?

SpringAOP的底层主要基于动态代理技术 (JDK动态代理、Cglib动态代理)

介绍一下代理模式?分类?JDK和cglib的区别?

JDK和cglib的具体实现,要求能口述?

代理对象 = Proxy.newInstance(类加载器,目标对象的所有接口,InvocationHandler接口的实例);

Enhancer  en = new Enhancer();
en .supperClass();
en.setCallback(); // 实现MethodInteceptor 的实例 
代理对象 = en.create();

Spring声明式事务,如何配置

注解方式配置
基于aop的tx标签配置

什么是事务的隔离级别,分成哪些隔离级别

Spring 默认使用数据的隔离级别
可以单独设置

什么是事务的传播行为,分成哪些传播行为

七种传播级别,重要的两种一定要记住
当发生事务嵌套时事务的情况要了解

SpringMVC的流程?

(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。

SpringMVC与Struts2的区别

1)springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter)。

(2)springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。

(3)Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。

如何解决POST请求中文乱码问题,GET的又如何处理呢?

(1)解决post请求乱码问题:
在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8
	<filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
(2)解决get请求乱码问题
String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
-- 原因:
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。

Mybatis面试题汇总

#{}和${}的区别是什么

#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。

##### 使用建议:

能用 #{} 的地方就用 #{},不用或少用 ${}

表名作参数时,必须用 ${}。如:select * from ${tableName}

order by 时,必须用 ${}。如:select * from t_user order by ${columnName}

使用 ${} 时,要注意何时加或不加单引号,即 ${} 和 '${}'

当实体类中的属性名和表中的字段名不一样,怎么办

> 写sql语句时起别名 ,别名和属性相对应  

> 在MyBatis的全局配置文件中开启驼峰命名规则 ,mybatis会将数据库中 下划线的字段自动转为驼峰格式的属性

> 在Mapper映射文件中使用resultMap来自定义映射规则

XML映射文件中,除了常见的Select|insert|update|delete标签之外,还有哪些标签

<if>   <choose>   <where> <trim>  <foreach> <bind> <resultMap> <sql> <collection>  ......随便说

动态sql的 foreach标签有哪些属性,如何使用

MyBatis动态SQL是做什么的,有哪些动态SQL,能简述一下动态SQL的执行原理吗

在执行sql语句时会根据 全限类名+方法名(cn.itcast.mapper.UserMapper.findAll)获取到
MappedStatement,
在MappedStatement的getBoundSql中,根据sqlSource把所有sql拼装,并通过SqlSourceBuilder#parse的处理,把sql中的 在得到BoundSql之前,通过SqlNode#apply把sql都拼接起来,然后SqlSourceBuilder会把xml配置的变量处理为sql预执行中的"?",最终构建为sqlsource.进而得到BoundSql,BoundSql包含了sql和变量参数值

通过一个XML映射文件,都会写一个Mapper接口与之对应,请问,这个Mapper接口的工作原理。

回答mybatis的运行原理

Mapper接口里的方法,参数不同时,方法能重载吗

不可以,不论是注解配置的mybatis 还是xml配置的mybatis,被解析后每个方法都会封装成一个MappedStatement 存储到一个map集合中,集合的key使用的是mapper接口的全限类名+方法名,value就是MappedStatement对象。 
如: 
我想写个重载方法 findUser  一个带ID参数 返回值User 一个不带参数 返回值为List<User>  但是这个方法在map中寻找时都是以 xxx.UserMapper.findUser作为key  ,会发生冲突  实际上这个时候mybatis也会报错。

Mapper接口绑定有几种实现方式,分别是怎样实现的

-- 一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定
@Select("select * from `tb_Teacher` where id = #{id}")
public teacher  selectTeacherByID(int id);
-- 另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。
<select id="selectUserByID" parameterType="int" resultType="test.student">
	select id,name,age,stuCountry stu_country from `tb_Student` where id = #{id}
</select>

MyBatis的XML Mapper文件中,不同的XML映射文件,id是否可以重复

如果是不同的namespace ,定义方法的id是可以重复的,因为mapper接口的方法映射 是全限类名+方法名

如何获取自动生成的(主)键值

1.可以通过查询最后一条的sql语句
 <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
      SELECT LAST_INSERT_ID()
 </selectKey>
2.也可以通过mybatis的标签属性 useGeneratedKeys  
<insert id="insertSelective" parameterType="cn.tencent.eee.aaa.dao.model.User" 		useGeneratedKeys="true" keyProperty="id">
</insert>

MyBatis执行批量插入,能返回数据库主键列表吗

// 可以的  设置好useGeneratedKeys 属性  和 keyProperty属性
 <insert id="insertBatchIds" useGeneratedKeys="true" keyProperty="id">
	  insert into t_user_score(user_id,score,created_at) values
	  <foreach collection="list" item="obj" separator=",">
	       (#{obj.userId}, #{obj.score}, now())
	   </foreach>
 </insert>

在Mapper中如何传递多个参数

> 通过实体类传参

> 通过map传参

> 通过定义多个@Param注解传参

MyBatis是否可以映射Enum枚举类

可以的**,MyBatis内置了两个枚举转换器分别是:

**EnumTypeHandler**
这是默认的枚举转换器,该转换器将枚举实例转换为实例名称的字符串,即将UserSex.MALE转换MALE。
**EnumOrdinalTypeHandler**
顾名思义这个转换器将枚举实例的ordinal属性作为取值,即UserSex.MALE转换为0,UserSex.FEMALE转换为1。
使用它的方式是在MyBatis配置文件中定义:

<typeHandlers>
    <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.example.entity.enums.ComputerState"/>
</typeHandlers>

如果以上枚举处理类满足不了我们的需求,我们也可以自定义枚举类型转换器,MyBatis提供了`BaseTypeHandler`类用于我们自己扩展类型转换器,上面的`EnumTypeHandler`和`EnumOrdinalTypeHandler`也都实现了这个接口。

MyBatis都有哪些Executor执行器,它们之间的区别是什么

SimpleExecutor
简单执行器(默认),每次执行CRUD都会创建一个PreparedStatement去执行sql
ReuseExecutor
可复用的执行,执行CRUD会查看缓存,缓存没有才会创建一个PreparedStatement去执行sql,并缓存该执行对象
BatchExecutor
批处理执行器,用于执行批量处理

MyBatis如何执行批量插入

1.方式1, 通过mybatis的动态标签,已批量新增为例   比较常用
<!-- 批量新增-->
<insert id="batchSave" parameterType="java.util.List">
    INSERT INTO lp_user_test_batch
    (
    id,
    user_id,
    user_name
    )
    VALUES
    <foreach collection="list" item="item" index="index" separator=",">
        (
        #{item.id,jdbcType=BIGINT},
        #{item.userId,jdbcType=VARCHAR},
        #{item.userName,jdbcType=VARCHAR}
        )
    </foreach>
</insert>
2.利用 MyBatis 批处理特性,批量提交(ExecutorType.BATCH)
public void batchInsert(List<UserTestBatchDO> testBatchDAOList) {
    //集合非空
    if (CollectionUtils.isEmpty(testBatchDAOList)) {
        return;
    }
    //批处理方式 SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
    //获得对应的Mapper
    UserTestBatchDOMapper userTestBatchDOMapper = sqlSession.getMapper(UserTestBatchDOMapper.class);
    try {
        for (UserTestBatchDO testBatchDO : testBatchDAOList) {
            userTestBatchDOMapper.insert(testBatchDO);
        }
        //统一提交
        sqlSession.commit();
    } catch (Exception e) {
        //没有提交的数据可以回滚
        sqlSession.rollback();
    } finally {
        //关闭 sqlSession
        sqlSession.close();
    }
}

简单介绍一下MyBatis的一级缓存和二级缓存的概念和实现原理

一级缓存:默认开启
一级缓存的范围是同一个SqlSession对象,当我们使用SqlSession对象进行查询时mybatis会帮我们把查询的数据存入到内存中,当我们在这个SqlSession中再一次执行同样的查询操作时,我们就可以直接去缓存中获取数据

二级缓存:默认关闭  
二级缓存是mapper级别的缓存,多个SqlSession共享,其作用域是mapper的同一个namespace,不同的SqlSession两次执行相同的namespace下的sql语句,且向sql中传递的参数也相同,即最终执行相同的sql语句,则第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。

一级缓存 和 二级缓存的执行顺序
二级缓存    ———>    一级缓存    ——>    数据库

MyBatis是否支持延迟加载,如果支持,如何实现

> 支持延迟加载
> 在核心配置文件中开启延迟加载
     在关联标签中  fetchType 设置为lazy

MyBatis能否一对一、一对多的关联查询,都有哪些实现方式,它们之间的区别是什么

在xml中定义映射关系, 使用association代表关联一个实体类, property映射的属性名,javaType该属性的实体类类型,fetchType是否延迟加载,column用于执行select方法所传递的参数,select需要执行的mapper方法的全限定名称

在xml中定义映射关系,因为是一个集合 所以使用collection标签,ofType代表集合中实体类的类型,其他属性和上面对一的情况一致

MyBatis是如何进行分页的,分布插件的原理是什么

可以通过pageHelper插件实现分页
<!-- 配置分页插件 -->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageHelper">
        <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
        <property name="dialect" value="mysql"/>
    </plugin>
</plugins>
PageHelper.startPage(1,1); // 在代码中执行startPage方法  第一个参数第几页,第二个是几条数据

PageHelper分页的实现在我们执行SQL语句之前动态的将SQL语句拼接了分页的语句,从而实现了从数据库中分页获取数据的过程。

MyBatis与Hibernate有哪些不同

(1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。

(2)Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。 

(3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用hibernate开发可以节省很多代码,提高效率。

MyBatis映射文件中,如果A标签通过include引用了B标签的内容,请问,B标签能否在A标签的后面,还是说必须定义在A标签的前面

可以定义在A标签的后边

简述MyBatis的XML映射文件和MyBatis内部数据结构之间的映射关系

Mybatis将所有Xml配置信息都封装到All-In-One重量级对象Configuration内部。在Xml映射文件中,<parameterMap>标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象。<resultMap>标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个<select>、<insert>、<update>、<delete>标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象。

Mybatis中使用到了哪些设计模式

**Builder模式**,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;
**工厂模式**,例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;
**单例模式**,例如ErrorContext和LogFactory;
**代理模式**,Mybatis实现的核心,比如MapperProxy、ConnectionLogger,用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果;
**装饰者模式**,例如Cache包中的cache.decorators子包中等各个装饰者的实现;
**组合模式**,例如SqlNode和各个子类ChooseSqlNode等;
**模板方法模式**,例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler;
**适配器模式**,例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现;
**迭代器模式**,例如迭代器模式PropertyTokenizer;
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值