Java面试总结(七)

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

  1. #{}是预编译处理,$ {}是字符串替换。

  2. mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;mybatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。

  3. 使用 #{} 可以有效的防止SQL注入,提高系统安全性。

  4. 排序语句建议使用 ${}

如果想要详细了解这个问题,可以参考这篇文章——详解

Mybaits的优缺点

优点

  1. 基于 sql 语言编程,不会对现有的应用程序或数据库设计有任何影响;
  2. sql 语句都写在 xml 文件中,实现了代码和sql语句得解耦,便于统一管理 sql 语句;
  3. 相较于 JDBC 减少了大量冗余代码,不用手动创建释放连接;
  4. 数据库兼容性好(基于 JDBC 连接数据库,JDBC 支持得数据库 mybatis 都支持)
  5. 可以与 Spring 很好的集成。
  6. 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

缺点

  1. 需要手动编写大量的 sql ,尤其是字段多、需要关联很多表时;
  2. 数据库可移植性差(sql 语言依赖于数据库,不同的数据库 sql 语言有所不同)。

逻辑分页(内存分页)和物理分页

物理分页

物理分页依赖的是某一物理实体,这个物理实体就是数据库,比如MySQL数据库提供了limit关键字,程序员只需要编写带有limit关键字的SQL语句,数据库返回的就是分页结果。

逻辑分页

逻辑分页依赖的是程序员编写的代码。数据库返回的不是分页结果,而是全部数据,然后再由程序员通过代码获取分页数据,常用的操作是一次性从数据库中查询出全部数据并存储到List集合中,因为List集合有序,再根据索引获取指定范围的数据。

对比

  1. 数据库负担:物理分页每次都访问数据库,逻辑分页只访问一次数据库,物理分页对数据库造成的负担大。

  2. 服务器负担:逻辑分页一次性将数据读取到内存,占用了较大的内容空间,物理分页每次只读取一部分数据,占用内存空间较小。

  3. 实时性:逻辑分页一次性将数据读取到内存,数据发生改变,数据库的最新状态不能实时反映到操作中,实时性差。物理分页每次需要数据时都访问数据库,能够获取数据库的最新状态,实时性强。

  4. 适用场合:逻辑分页主要用于数据量不大、数据稳定的场合,物理分页主要用于数据量较大、更新频繁的场合。

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

MyBatis 使用 Rowbounds 对象进行分页,它是根据 ResultSet 执行内存分页而非物理分页。可以在 sql 中直接书写物理分页参数来完成物理分页功能。也可以使用分页插件实现物理分页功能。

分页插件的基本原理就是根据 mybatis 提供的插件接口,自定义分页插件,在插件的拦截方法内拦截执行的 sql,然后重写 sql,根据 dialect 方言, 添加对应的物理分页语句和物理分页参数。

MyBatis 使用 RowBounds 实现的分页是逻辑分页,也就是先把数据记录全部查询出来,然在再根据 offset 和 limit 截断记录返回(数据量大的时候会造成内存溢出),不过可以用插件或其他方式能达到物理分页效果。

为什么说 MyBatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?

Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 MyBatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。

Mybatis 缓存

如果想要详细了解这个问题,可以参考这篇文章——mybatis的一级缓存和二级缓存

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

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

第二种是使用sql列的别名功能,将列的别名书写为对象属性名。

有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

Mybatis动态sql有什么用?执行原理?有哪些动态sql?

Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值 完成逻辑判断 并动态拼接sql的功能。

Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。

使用MyBatis的mapper接口调用时有哪些要求?

Mapper接口方法名和mapper.xml中定义的每个sql的id相同;
Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;
Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;
Mapper.xml文件中的namespace即是mapper接口的类路径。

i++ 和 ++i

  • i++是先赋值,然后再自增;++i是先自增,后赋值。

  • i++ 不能作为左值,而++i 可以。左值是对应内存中有确定存储地址的对象的表达式的值,而右值是所有不是左值的表达式的值。一般来说,左值是可以放到赋值符号左边的变量。

i++ 是一个复合操作,分为如下三步:

  1. 读取 i 的值。
  2. 对 i 加 1。
  3. 将 i 的值写回内存。

List Set Map的使用场景

说说 List,Set, Queue, Map 四者的区别?

  • List:有序可重复;
  • Set:无序不可重复;
  • Queue:有序可重复;
  • Map:无需,key 不可重复,value 可重复

如果你经常会使用索引来对容器中的元素进行访问,那么List是你的正确的选择。如果你已经知道索引了的话,那么List的实现类比如ArrayList可以提供更快速的访问,如果经常添加删除元素的,那么肯定要选择LinkedList。

如果你想容器中的元素能够按照它们插入的次序进行有序存储,那么还是List,因为List是一个有序容器,它按照插入顺序进行存储。

如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个Set的实现类,比如 HashSet、LinkedHashSet或者TreeSet。所有Set的实现类都遵循了统一约束比如唯一性,而且还提供了额外的特性:比如TreeSet还是一个SortedSet,所有存储于TreeSet中的元素可以使用Java里的Comparator或者Comparable进行排序。LinkedHashSet也按照元素的插入顺序对它们进行存储。

如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。

总之要根据集合特性进行合适选择。

两层循环内层break会咋样

只会跳出内层循环。

如何跳出两层循环?

使用 OUT 标识符

public static void main(String[] args) {
        test();
    }
    public static void test(){
        for(int i = 0; i < 3; ++i){
            for(int j = 0; j < 1; ++j){
                if(i == 1) break ;
                System.out.println(i + ":" + j);

            }
        }
    }

Output:

0:0
2:0
public static void main(String[] args) {
        test();
    }
    public static void test(){
        OUT:
        for(int i = 0; i < 3; ++i){
            for(int j = 0; j < 1; ++j){
                if(i == 1) break OUT;
                System.out.println(i + ":" + j);

            }
        }
    }

Output:

0:0
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上阡陌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值