SSM框架常见面试题

本文详细解释了Mybatis的执行流程、配置核心功能、输入输出映射、缓存机制、多表查询、与SpringMVC的对比,以及SpringMVC的执行流程和参数绑定。涵盖了Mybatis的基础使用和高级特性。
摘要由CSDN通过智能技术生成

【1】请说明一下Mybatis执行流程

  1. 初始化Mybatis框架运行环境(加载配置文件:SqlMapConfig.xml、mapper.xml)。
  2. 根据配置信息构建SqlSessionFactory。
  3. 使用SqlSessionFactory创建数据库连接实例SqlSession
  4. SqlSession实例调用内部的Executor执行器
  5. 执行器把传入参数映射到MappedStatement中的sql语句中,相当于JDBC中的预编译、设置参数,Mapper.xml中配置每条sql语句都是一个MappedStatement。
  6. 完成数据库操作后,会把输出结果进行封装,相当于JDBC中的结果解析的过程。

【2】请说一下你应用Mybatis的过程

  1. 导入依赖
  2. 编写核心配置文件与日志文件(整合mybatis环境)
  3. 依据数据库编写实体类
  4. 编写mapper接口与mapper.xml配置文件
    1. 对应的mapper配置文件的namespace属性值必须是Mapper接口的全类名
    2. Mapper接口中的方法名必须与mapper配置文件中对应的id值相同
    3. Mapper接口的方法的参数类型必须与mapper配置文件中配置的parameterType类型匹配上
    4. Mapper接口的方法返回值类型必须与mapper配置文件中配置的resultType类型匹配上
  5. 根据不同的sql编写不同的标签,select,instert,delete,update标签

【3】请说一下SqlMapConfig核心配置功能

  1. 所有标签都有配置顺序
  2. properties标签引入数据源
  3. setting全局设置驼峰式、缓存、日志、延迟加载
  4. 别名配置
  5. mapper配置

【4】请说一下Mybatis的输入映射与输出映射

输入映射指的是标签parameterType与mapper接口参数之间的映射

  1. 简单类型使用#{}可以写入任意值
  2. JavaBean #{参数名}必须和JavaBean的字段名保持相同
  3. 包装类类型 #{参数名}必须和属性对象.属性名字保持相同;严格遵循OGNL表达式
  4. 多参数类型,多个参数的参数名需要@param(参数名)指定,占位符直接使用#(参数名)
  5. Map类型,#{}的参数必须是和map集合的key的名字相同

输出映射指的是ResultType属性和mapper接口方法返回值之间的映射

  1. 简单类型映射
  2. JavaBean类型映射返回字段必须和JavaBean名字相同,可开启驼峰式,让user_id userId
  3. 复杂类型用ResultMap指定映射关系

可以配置插入数据生成id值

<!--返回自动生成的id值
    1.useGeneratedKeys 打开使用自动生成id的开关
    2.keyColumn 数据库表返回的主键字段
    3.keyProperty javaBean类中属性对应的名字
    -->
<insert id="insertUserReturnId" parameterType="user" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
    insert into t_user(username,address,description) values(#{username},#{address},#{description})
</insert>
<insert id="insertUserReturnId" parameterType="user">
    <!--selectKey 配置的是获取id值的sql函数
                1.keyColumn 数据库主键
                2.keyProperty="id" 类中属性名
                3.resultType 主键返回的类型
                4.order:只能配置两个值AFTER、BEFORE
                    1.AFTER代表函数在添加sql语句执行后执行
                    2.BEFORE代表函数在添加sql语句执行前执行
        -->
    <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
        select last_insert_id()
    </selectKey>
    insert into t_user(username,address,description) values(#{username},#{address},#{description})
</insert>

【5】mybatis动态标签有哪些

  1. if
  2. where
  3. choose、when、otherwise
  4. foreach

【6】请你说明一下mybatis缓存

mybatis分为一级缓存和二级缓存

一级缓存是sqlsession内部间的缓存

查询sql语句时,优先从一级缓存中获取数据,如果没有,查询数据库,将数据库查询结果返回给一级缓存,然后再返回。

二级缓存时sqlsession间的缓存,也就是多个sqlsession之间的缓存

如果开启二级缓存,查询sql语句时,优先从二级缓存中查找结果,如果没有去一级缓存中查找,如果没有找到则去数据库查询,将查询结果先存入一级缓存,再存入二级缓存,再返回。

【7】请说明一下Mybatis如何实现多表查询

一对一关联查询,通过resultMap标签进行映射,用association子标签一对一映射关系

一对多关联查询,通过resultMap标签进行映射,用cllection子标签标识一对多映射关系

延迟加载指的是如果只是用主对象数据,那么只查询主sql语句,只有调用主对象的子属性时,采取调用collection/association标签的select属性关联的子查询sql语句。

【8】什么是Mybatis?

  1. Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等复杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高
  2. Mybatis可以使用XML或注解来配置和映射原生信息,将POJO映射成数据库中的记录,避免了几乎所有JDBC代码和手动设置参数以及获取结果集
  3. 通过xml文件或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)

【9】Mybatis的优点:

  1. 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
  2. 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接
  3. 很好的与各种数据库兼容(因为Mybatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)
  4. 能够与Spring很好的集成
  5. 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护

【10】Mybatis框架的缺点

  1. Sql语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定的要求
  2. Sql语句依赖于数据库,导致数据移植性差,不能随意更换数据库。

【11】Mybatis框架适用场合

  1. Mybatis专注于SQL本身,是一个足够灵活的DAO层解决方案
  2. 对性能的要求很高,或者需求变化较多的项目,如互联网项目,Mybatis将是不错的选择

【12】Mybatis与Hibernate有哪些不同?

Mybatis和Hibernate不同,它不完全是一个ORM框架,因为Mybatis需要程序员自己编写sql语句

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

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

【13】#{}和${}的区别是什么?#{}是预编译处理,${}是字符串替换

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

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

第一种:通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致

第二种:通过<resultMap>来映射字段名和实体类属性名的一一对应的关系。

【15】通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

Dao接口即Mapper接口。接口的全限定名,就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法内的参数,就是传递给sql的参数。Mapper接口时没有实现类的,当调用接口方法时,接口全限定名+方法名拼接字符串作为key值,可唯一定位一个MapperStatement。在Mybatis中,每个<select>、<insert>、<update>、<delete>标签,都会解析为一个MapperStatement对象。举例: com.mybatis3.mappers.StudentDao.findStudentById ,可以唯一找到 namespace 为 com.mybatis3.mappers.StudentDao 下面 id 为findStudentById 的 MapperStatement。Mapper接口里的方法,是不能重载的,因为是使用全限定名+方法名的保存和寻找策略。Mapper接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,转而执行MapperStatement所代表的sql,然后将sql执行结果返回。

【16】Mybatis是如何进行分页的?分页插件的原理是什么?

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。分页插件的基本原理是使用Mybatis提供的插件插口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数

【17】Mybatis是如何将sql执行结果封装为目标对象并返回的?有哪些映射形式?

第一种是使用<resultMap>标签,逐一定义数据库列名和对象属性名之间的映射关系。

第二种是使用sql列的别名功能,即resultType属性映射。将列的别名书写为对象属性名。有了列名和属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

【18】IOC和DI的概念

IOC是控制反转,指的是将对象的创建权交给Spring框架IOC容器与维护,IOC容器底层就是CurrentHashMap集合,通过反射加载配置文件或配置类创建对象放入集合中。DI是依赖注入,指的是SpringIOC容器帮助我们将配置文件中的属性以setter方法或构造方法或字段的方式注入。

【19】IOC的实现方式与DI的实现方式

IOC的实现方式

  1. xml实现
    1. 构造方法
    2.  静态工厂
    3. 实例工厂
  2. xml+注解实现
    1. 包扫描+注解
    2. @Controller
    3. @Service
    4. @Repository
    5. @Component
  3. 配置类实现
    1. @Configuration+@Bean

DI的实现方式

  1. xml
    1. setter方法
    2. 构造方法
    3. springEL表达式注入#{SpringEL表达式}
  2. 注解
    1. @Autowired按照自动注入
    2. @Autowired+@Qualifier按照类型自动注入,如果失败按照名字注入
    3. @Resource按照名字注入
    4. @Value注入简单类型 支持${}表达式读取properties内容,支持#{}SpringEL表达式

【20】配置类常用注解

  1. @Configuration 表示当前类是一个配置类

  2. @Bean 相当于bean标签

  3. @PropertySource 引入properties配置文件

  4. @Import 导入其他配置类

【21】SpringIOC的生命周期

  1. singleton(单例Bean)
    • 初始化:容器初始化时就会创建Bean,可以通过延迟加载设置,如果lazy-init=true在获取对象的时候才创建并初始化
    • 存活:只要容器存在,Bean就一直存在
    • 销毁:当容器销毁时,Bean也被销毁
  2. prototype(多例Bean)
    1. 初始化:每一次访问Bean实例的时候,创建Bean
    2. 存活:只要Bean实例被使用,Bean就一直存在
    3. 销毁:当Bean实例不常用时,会被Java的回收机制自动回收

【22】JDK动态代理与CGlib动态代理

  • 原理区别
    • JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法之前调用InvocationHandler
    • CGLIB动态代理是利用ASM开源包,对代理类的class文件进行字节码修改,生成被代理类的子类,覆盖目标方法
  • 依赖区别
    • JDK动态代理,不需要第三方的库,只要JDK环境就可以;
    • CGLIB动态代理,需要加入cglib、asm的类库
  • 要求区别
    • JDK动态代理,被代理的类必须有实现的接口
    • CGLIB动态代理,针对具体的实现类进行代理,但是类不能final修饰
  • 编程区别
    • JDK动态代理,需要实现InvocationHandler接口编写增强、使用Proxy.newInstance获取代理对象
    • CGLIB动态代理,实现MethodInterceptor接口中的invoke方法实现增强,使用Enhancer根据被代理对象和增强修改字节码文件。

【23】AOP面向切面编程概念

  1. AOP的概念
  • AOP打破传统意义的面向对象的纵向编程,底层依赖GDK/CGLIB动态代理+配置文件实现面向切面编程,将程序升级为横向编程。具体实现过程是通过动态代理将某个程序执行过程中植入前置通知/返回通知/环绕通知/异常通知的过程。
  1. AOP配置
    1. 配置目标类
    2. 配置AOP配置
      1. 配置切入点
      2. 配置切面

@Aspect表示是一个切面类

【24】简述事务

事务是逻辑上的一组操作,要么都执行,要么都不执行

事务要满足acid执行原则

  • 原子性(Atomicity):是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用
  • 一致性(Consistency):执行事务前后,数据保持一致
  • 隔离性(Isolation):并发访问数据库时,一个用户的事物不被其他事物所干扰,各并发事务之间数据库时独立的
  • 持久性(Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

事务的隔离级别

  1. 读未提交(ISOLATION_READ_UNCOMMITTED) 可能发生脏读、可重复读、幻读

  2. 读并且提交(ISOLATION_READ_COMMITTED )避免脏读,不能避免可重复读,幻读的发生

  3. 可重复读(ISOLATION_REPEATABLE_READ)避免脏读,不可重复读问题的发生,不能避免幻读发生

  4. 串行化(ISOLATION_SERIALIZABLE) 避免脏读,不可重复读、幻读发生。

Spring事务管理接口

  1. PlatformTransactionManager 指定事务管理器
  2. TransactionDefinition 事务的定义信息
  3. TransactionStatus 事务的状态记录

事务注解:@Transactional

事务传播行为

  1. PROPAGATION_REQUIRED 如果当前存在事务,则加入该事务; 如果当前没有事务,则创建一个新的事务。【默认】

  2. PROPAGATION_REQUIRES_NEW 创建一个新的事务,如果当前存在事务,则把当前事务挂起。

【25】SpringMVC执行流程

  1. 浏览器发送请求至应用程序,被前端控制器(DispatcherServlet)接收;
  2. 前端控制器调用处理器映射器(HandlerMapping)查找处理器(Handler)
  3. 处理器映射器根据请求映射到Spring容器中获取得到处理器(Handler,也是自定义的Controller);
  4. 处理器映射器组装处理器执行链(HandlerExecutionChain),返回给前端控制器;
  5. 前端控制器找到合适的处理器适配器(HandlerAdapter);
  6. 处理器适配器执行处理器,处理器(Controller)执行完成后返回模型和视图(ModelAndView);
  7. 处理器适配器把模型和视图返回给前端控制器
  8. 前端控制器调用视图解析器(ViewReslover)解析模型和视图(ModelAndView)
  9. 视图解析器进行视图渲染(即把模型数据填充到视图中),最终响应浏览器的请求

【26】SpringMVC常用注解

  1. @Controlelr

  2. @RequestMapping

  3. @RestController = @ResponseBody+@Controller

  4. @ControllerAdvice 开启springMVC的全局异常处理包扫描 ,处理服务器端渲染开发

  5. @RestControllerAdvice 开启springMVC的全局异常处理包扫描 ,处理前后端分离开发

  6. @PostMapping @GetMapping @DeleteMapping @ PutMapping @RequestMapping

  7. @ResponseBody @RequestBody

  8. @PathVariable @RequestParam

【27】SpringMVC如何配置请求转发,重定向,如何存储转发数据

controller方法返回值return"逻辑视图"请求转发return "redirect:"重定向方法参数上的Model/ModelMap/Result存储

【28】SpringMVC的参数绑定

  1. 简单类型参数绑定,如果提交的参数key和参数名字不一致,用@RequestParam注解处理
  2. JavaBean类型的参数绑定
  3. 数组类型绑定
  4. 简单集合类型绑定
  5. @RequestBody接收浏览器提交json数据
  6. @PathVariable接收restful风格路径上的参数

【29】除了基本的SpringMVC操作外,还用过哪些功能?

  1. 自定义类型转换器
    1. 实现Converter接口
    2. 配置类型转换器
  2. SpringMVC常用标签
    1. 静态资源映射:

      <mvc:resources mapping="/js/**" location="/js/" />

      <!--对静态资源放行--> <mvc:default-servlet-handler />

    2. <mvc:view-controller path="/loginUI" view-name="login" />

  3. 文件上传

    1. 表单post请求

    2. 表单类型设置为mutipart/form-data

    3. 编写代码

 public String update(MultipartFile img){
        String newFileName = null;
        try {
            //获得上传的名字
            String filename = img.getOriginalFilename();
            newFileName = new Date().getTime()+(int)(Math.random()*(100))+filename;
            System.out.println(baseUrl);
            //上传到指定位置
            img.transferTo(new File(baseUrl+"/"+newFileName));
        } catch (IOException e) {
            e.printStackTrace();
            return "no";
        }
        return newFileName;
    }
  1. 处理器拦截器

    1. 实现HandlerInterceptor接口

      1. preHandle controlelr代码执行前执行

      2. postHandle controller代码执行后执行

      3. afterCompletion 页面渲染后执行

    2. 配置拦截器

  2. 异常处理机制

    1. @ControllerAdvice+ @ExceptionHandler 处理服务器端渲染开发的全局异常

    2. @RestControllerAdvice+@ExceptionHandler 处理前后端分离开发的全局异常

    3. 实现HandlerExceptionResolver 接口编写自定义方案异常处理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值