Java面试题

这篇博客详细梳理了Java面试的重点内容,包括但不限于:重载与重写、String与StringBuilder的区别、==与equals的区别、synchronized关键字的使用、抽象类与接口的区别、集合类的区别、HashMap与Hashtable的实现原理、线程安全问题、线程状态与同步机制、设计模式在Spring框架中的应用、Redis的使用场景与数据类型、以及MyBatis的注解使用等。这些知识点涵盖了多线程、数据结构、并发控制、数据库操作等多个方面,是准备Java面试的重要参考资料。
摘要由CSDN通过智能技术生成

第一天:

1.重载和重写的区别

什么是方法重写

​ 在Java和其他一些高级面向对象的编程语言中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。

方法重写和方法重载的区别:

​重载(overload):发生在同一个类中 , 方法名相同,参数列表不同,不考虑返回值。同名的方法如果有不同的参数列表(类型不同、个数 不同、顺序不同)则视为重载。

重写(overrides):发生在父子类中,子类继承父类的方法,方法名相同,参数也相同,但是实现方法体不同。

重写的注意事项 

  • 必须保证父子类中重写的方法,方法名相同,参数列表相同。
  • 子类方法的返回值必须小于或等于父类方法的返回值范围。
  • 子类方法的权限必须要大于等于父类方法的权限(不包括 private)
  • 子类重写方法异常声明必须是父类的异常或子级异常
  • 私有的不能被继承

2.String 和 StringBuffer、 StringBuilder 的区别是什么?

可变性

String 类中使用 final 关键字修饰字符数组来保存字符串,所以 String 对象是不可变的。 而StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是 使用字符数组保存字符串char[]value 但是没有用 final 关键字修饰, 所以这两种对象都是可变的。

线程安全性

String 中的对象是不可变的,也就可以理解为常量,线程安全。

StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是 线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程 安全的。

性能

每次对 String 类型进行改变的时候,都会生成一个新的 String 对象, 然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引 用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获 得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险

3.== 与 equals 的区别

对于基本类型和引用类型 == 的作用效果是不同的,基本类型:比较的是值 是否相同; 引用类型:比较的是引用是否相同;

equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较

4.说说自己是怎么使用 synchronized 关键字,在项目 中用到了吗?

修饰实例方法

作用于当前对象实例加锁,进入同步代码前要获得当前对象 实例的锁

修饰静态方法

作用于当前类对象加锁,进入同步代码前要获得当前类对象 的锁

修饰代码块

指定加锁对象,对给定对象加锁,进入同步代码库前要获得给 定对象的锁。

双重校验锁实现对象单例(线程安全)

使用场景

public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
//先判断对象是否已经实例过,没有实例化过才进入加锁代码
if (uniqueInstance == null) {
//类对象加锁
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}

5.抽象类和接口的区别是什么?

 实现:

抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。

构造函数:

抽象类可以有构造函数;接口不能有。

实现数量:

类可以实现很多个接口;但只能继承一个抽象类【java只支持单 继承】。

访问修饰符:

接口中的方法默认使用 public 修饰;抽象类中的抽象方法 可以使用Public和Protected修饰,如果抽象方法修饰符为Private,则 报错:The abstract method 方法名 in type Test can only set a visibility modifier, one of public or protected。 接口中除了static、final变量,不能有其他变量,而抽象类中则不一定

设计层面:

抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象, 是一种行为的规范。


第二天:

1.Collection 和 Collections 有什么区别? 

Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口 方法,所有集合都是它的 子类,比如 List、Set 等。

Collections 是一个包装类,包含了很多静态方法,不能被实例化, 就像一个 工具类,比如提供的排序方法: Collections. sort(list)

2 .List、Set、Map 之间的区别是什么?

3.HashMap 和 Hashtable 有什么区别? 

存储:

HashMap 运行 key 和 value 为 null,而 Hashtable 不允许。

线程安全:

Hashtable 是线程安全的,而 HashMap 是非线程安全的。

推荐使用:

在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使 用 , 推 荐 在 单 线 程 环 境下 使 用 HashMap 替 代 , 如 果 需 要 多 线 程使 用 则 用 ConcurrentHashMap 替代。

 4. 说一下 HashMap 的实现原理?

HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。 当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的 做法是用链表和红 黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链 表否则使用红黑树。

5.说一下 HashSet 的实现原理? 

HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相 关方法来完成, HashSet 不允许重复的值。


第三天:

1.ArrayList和LinkedList的区 别

 ArrayList:

基于动态数组,连续内存存储,适合下标访问(随机访问),扩 容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组 的数据拷贝到新数组,如果不是尾部插入数据还会涉及到元素的移动(往后复 制一份,插入新元素),使用尾插法并指定初始容量可以极大提升性能、甚至 超过linkedList (需要创建大量的node对象)

LinkedList:

基于链表,可以存储在分散的内存中,适合做数据插入及删除 操作,不适合查询:需要逐一遍历,遍历LinkedList必须使用iterator, 不能使用for循环,因为每次for循环体内通过get(i)取得某一元素时都需 要对list重新进行遍历,性能消耗极大。

2.ConcurrentHashMap原 理,jdk7和jdk8版本的区别

https://blog.csdn.net/qq_38525526/article/details/99624132https://blog.csdn.net/qq_38525526/article/details/99624132

jdk7:

数据结构:

ReentrantLock+Segment+HashEntry,一个Segment中包 含了一个HashEntry数组,每个HashEntry又是一个链表结构。

元素查询:

二次hash,第一次hash定位到Segment,第二次hash定位元 素所在链表的头部

锁:

Segment分段锁,Segment继承了ReentrantLock,锁定操作的 Segment,其他Segment不受影响,并发度为Segment的个数,可以通过 构造函数指定,数组扩容不影响其他Segment get方法无须加锁, volatile保证 

jdk8:

数据结构:

synchronized+CAS+Node+红黑树,Node的val和next都用 volatile修饰,保证可见性

查找,替换,赋值操作都使用CAS

锁:

锁链表的head节点,不影响其他元素的读写,锁粒度更细,效率更 高,扩容时,阻塞所有读写操作,并发扩容

读操作无锁:Node的val和next使用volatile修饰,读写线程对该变量 互相可见

数组使用volatile修饰,保证扩容时被读线程感知。

3.哪些集合类是线程安全的?

 Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非 线程安全 的,不过在JDK1.5之后随着 Java.util.concurrent 并发包 的出现,它们也有 了 自 己 对 应 的 线 程 安 全 类 , 比 如 HashMap 对 应 的 线 程 安 全 类 就 是 ConcurrentHashMap.

4.创建线程有哪几种方式

创建线程有三种方式:

继承 Thread 重写 run 方法;

实现 Runnable 接口;

实现 Callable 接口。 

5.说一下 runnable 和 callable 有什么区别?

runnable 没有返回值,callable 可以拿到有返回值,callable 可以 看作是 runnable 的补充。 


第四天:

1.线程有哪些状态?

 当线程对象对创建后,即进入了新建状态(NEW);

当调用线程对象的start()方法(t.start();)线程即进入就绪状态(Runnable);

CPU获取到时间片,进入到运行状态(Running);

当线程调用 wait()或者sleep()时,进入阻塞状态(Blocked),

当休眠时间结束后,或者调用notify或 notifyAll时会重新进入就绪状态(Runnable),再重新获取时间片,进入运行状态

线程执行完了或 者因异常退出了run()方法,该线程结束生命周期,进入终结状态(Dead)

2.sleep() 和wait() 有什么区别?

类的不同:

sleep() 来自 Thread,wait() 来自 Object。

释放锁:

sleep() 不释放锁;wait() 释放锁。

用 法 不 同

sleep() 时 间 到 会 自 动 恢 复 ; wait() 可 以 使 用 notify()/notifyAll()直接唤醒。 

3.notify()和 notifyAll()有什么区别?

notifyAll()会唤醒所有的线程,notify()之后唤醒一个线程。notifyAll() 调用后, 会将全部线 程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则 留在锁池等待锁被释放后 再次参与竞争。而 notify()只会唤醒一个线程,具体唤醒哪一个 线程由虚拟机控制。 

4.线程的 run() 和 start() 有什么区别?

start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复 调用,而 start() 只能调用一次。 

 5.说一说几种常见的线程池及适用场景?

FixedThreadPool:(固定线程池)

可重用固定线程数的线程池。(适用于负载比较重的服务器)

SingleThreadExecutor:(单一线程池)

只会创建一个线程执行任务。(适用于需要保证顺序执行各个任务;并且在 任意时间点,没有多线程活动的场景。)

CachedThreadPool:(缓存线程池)

是一个会根据需要调整线程数量的线程池。(大小无界,适用于执行很多的短期异 步任务的小程序,或负载较轻的服务器)

ScheduledThreadPool:(延迟线程池)

继承自ThreadPoolExecutor。它主要用来在给定的延迟之后运行任务,或 者定期执行任务。使用DelayQueue作为任务队列。


第五天:

1.线程池中 submit() 和 execute() 方法有什么区别?

execute():

只能执行 Runnable 类型的任务。

submit():

可以执行 Runnable 和 Callable 类型的任务。 Callable 类型的任务可以获取执行的返回值,而 Runnable 执行无返 回值。

2.在 Java 程序中怎么保证多线程 的运行安全?

方法一:

使用安全类,比如 Java. util. concurrent 下的类。

方法二:

使用自动锁 synchronized。

方法三:

使用手动锁 Lock 

3.什么是死锁?

当线程 A 持有独占锁 a,并尝试去获取独占锁 b 的同时,线程 B 持有独 占锁 b,并 尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互 相持有对方需要的锁,而发生 的阻塞现象,我们称为死锁。 

4.怎么防止死锁?

尽量使用 tryLock(long timeout, TimeUnit unit)的方法 (ReentrantLock、 ReentrantReadWriteLock),设置超时时间,超 时可以退出防止死锁。

尽量使用 Java. util. concurrent 并发类代替自己手写锁。

尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。

尽量减少同步的代码块

5.ThreadLocal 是什么?有哪些 使用场景? 

ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个 线程都可以独 立地改变自己的副本,而不会影响其它线程所对应的副本。

ThreadLocal 的经典使用场景是数据库连接和 session 管理等。 


第六天:

1.synchronized 和 Lock 有什 么区别?

synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码 块加锁。

synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自 动释放 锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不 当没有 unLock() 去释放锁就会造成死锁。

通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办 到。

2.什么是 Java 序列化?什么情况 下需要序列化?

Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象 状态再读出来。

以下情况需要使用 Java 序列化: 

想把的内存中的对象状态保存到一个文件中或者数据库中时候;

想用套接字在网络上传送对象的时候;

想通过 RMI(远程方法调用)传输对象的时候。

3.动态代理是什么?有哪些应用? 

动态代理是运行时动态生成代理类。

应用:

动态代理的应用有 spring aop、rpc, Java 注解对象获取等。

4.怎么实现动态代理?

JDK 原生动态代理和 cglib 动态代理。

JDK 原生动态代理是基于接口实 现的

cglib 是基于继承当前类的子类实现的。 

5.为什么要使用克隆?

克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都 还是初始化 时候的值,所以当需要一个新的对象来保存当前对象的“状态”就 靠克隆方法了。


第六天:

1.Redis 是什么?都有哪些使用 场景?

Redis 是一个使用 C 语言开发的高速缓存数据库。

Redis 使用场景: 

记录帖子点赞数、点击数、评论数;

缓存近期热点数据;

记录用户会话信息.

2. Redis 有哪些功能?

  • 数据缓存功能

  • 分布式锁功能

  • 支持数据持久化

  • 解决分布式会话

3.什么是缓存穿透?怎么解决?

缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据 库查询,查 不到数据则不写入缓存,这将导致这个不存在的数据每次请求都 要到数据库去查询,造成缓 存穿透 

解决方法:

1. 最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大 的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免 了对底层存储系统的查询压力。

2.另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查 询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个 空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

4.什么是缓存击穿?如何解决?

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这 时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数 据,引起数据库压力瞬间增大,造成过大压力。 

解决方法:

1.设置永久不过期。【这种只适合】

2.使用互斥锁(mutex key)业界比较常用的做法,是使用mutex。简单 地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的 SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功 时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方 法。

代码如下:

public String get(key) {
String value = redis.get(key);
if (value == null) { //代表缓存值过期
//设置3min的超时,防止del操作失败的时候,下次缓存过
期一直不能load db
if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {
//代表设置成功
value = db.get(key);
redis.set(key, value,
expire_secs);
redis.del(key_mutex);
} else { //这个时候代表同时候的其他线程已经
load db并回设到缓存了,这时候重试获取缓存值即可
sleep(50);
get(key); //重试
}
} else {
return value;
}
}

5. 什么是缓存雪崩?如何解决?

 缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据 库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发 查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数 据库。

解决方案: 

 1.缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

2.如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据 库中。

3.设置热点数据永远不过期。

第七天:

1.Redis 支持的数据类型有哪 些?

Redis 支持的数据类型:string(字符串)、list(列表)、hash(字 典)、set(集 合)、zset(有序集合)。

2.怎么保证缓存和数据库数据的 一致性?

  1. 合理设置缓存的过期时间。
  2. 新增、更改、删除数据库操作时同步更新 Redis,可以使用事物机制来 保证 数据的一致性

3.Redis 持久化有几种方式?

Redis 的持久化有两种方式,或者说有两种策略:

  • RDB(Redis Database):指定的时间间隔能对你的数据进行快照存 储。
  • AOF(Append Only File):每一个收到的写命令都通过 write 函 数追加到文 件中。

4.Redis 怎么实现分布式锁?

  1. Redis 分布式锁其实就是在系统里面占一个“坑”,其他程序也要占“坑”的 时候,占 用成功了就可以继续执行,失败了就只能放弃或稍后重试。
  2. 占坑一般使用 setnx(set if not exists)指令,只允许被一个程序占 有,使用完调用 del 释放锁。

5.Redis 淘汰策略有哪些?

  1. volatile-lru:从已设置过期时间的数据集(server. db[i]. expires)中挑 选最近最少使用的数据淘汰。
  2. volatile-ttl:从已设置过期时间的数据集(server. db[i]. expires)中挑 选将要过期的数据淘汰。
  3. volatile-random:从已设置过期时间的数据集(server. db[i]. expires)中 任意选择数据淘汰。
  4. allkeys-lru:从数据集(server. db[i]. dict)中挑选最近最少使 用的数据 淘汰。
  5. allkeys-random:从数据集(server. db[i]. dict)中任意选择数 据淘汰。
  6. no-enviction(驱逐):禁止驱逐数据。

第八天:

1.synchronized 和 Lock 有什 么区别?

  • synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码 块加锁。
  • synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自 动释放 锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不 当没有 unLock() 去释放锁就会造成死锁。
  • synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自 动释放 锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不 当没有 unLock() 去释放锁就会造成死锁。

2.什么是 Java 序列化?什么情况 下需要序列化?

Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象 状态再读出来。 以下情况需要使用 Java 序列化:

  • 想把的内存中的对象状态保存到一个文件中或者数据库中时候;
  • 想用套接字在网络上传送对象的时候;
  • 想通过 RMI(远程方法调用)传输对象的时候。

3.动态代理是什么?有哪些应 用?

动态代理是运行时动态生成代理类。

应用: 动态代理的应用有 spring aop、rpc, Java 注解对象获取等。

4.怎么实现动态代理?

JDK 原生动态代理和 cglib 动态代理。JDK 原生动态代理是基于接口实 现的,而 cglib 是基于继承当前类的子类实现的。

5.为什么要使用克隆?

克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都 还是初始化 时候的值,所以当需要一个新的对象来保存当前对象的“状态”就 靠克隆方法了。

第九天:

1..session 和 cookie 有什么区 别?

  • 存储位置不同:session 存储在服务器端;cookie 存储在浏览器端。
  • 安全性不同:cookie 安全性一般,在浏览器存储,可以被伪造和修改。
  • 容量和个数限制:cookie 有容量限制,每个站点下的 cookie 也有个 数限制。
  • 存储的多样性:session 可以存储在 Redis 中、数据库中、应用程序 中;而 cookie 只能存储在浏览器中。

2.如何避免 SQL 注入?

  • 使用预处理 PreparedStatement。
  • 使用正则表达式过滤掉字符中的特殊字符。

3.throw 和 throws 的区别?

  • throw:是真实抛出一个异常。
  • throws:是声明可能会抛出一个异常

4..final、finally、finalize 有什 么区别?

  • final:是修饰符,如果修饰类,此类不能被继承;如果修饰方法和变 量,则 表示此方法和此变量不能在被改变,只能使用。
  • finally:是 try{} catch{} finally{} 最后一部分,表示不论 发生任何情况 都会执行,finally 部分可以省略,但如果 finally 部 分存在,则一定会执行 finally 里面的代码。
  • finalize: 是 Object 类的一个方法,在垃圾收集器执行的时候会调 用被回 收对象的此方法。

5.常见的异常类有哪些?

  • NullPointerException 空指针异常
  • ClassNotFoundException 指定类不存在
  • NumberFormatException 字符串转换为数字异常
  • IndexOutOfBoundsException 数组下标越界异常
  • ClassCastException 数据类型转换异常
  • FileNotFoundException 文件未找到异常
  • NoSuchMethodException 方法不存在异常
  • IOException IO异常
  • SocketException Socket 异常

第十天:

1.说一下你熟悉的设计模式?

  • 单例模式:保证被创建一次,节省系统开销。
  • 工厂模式(简单工厂、抽象工厂):解耦代码。
  • 观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改 变时, 它的所有的依赖者都会收到通知并自动更新。\
  • 外观模式:提供一个统一的接口,用来访问子系统中的一群接口,外观定 义了 一个高层的接口,让子系统更容易使用。
  • 模版方法模式:定义了一个算法的骨架,而将一些步骤延迟到子类中,模 版方 法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。
  • 代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制 对原对象的引用

2.spring框架使用了那些设计模 式

1. spring的bean的创建默认使用单例模式

2. spring中获取bean对象通过的是工厂模式

3. spring的aop采用的是动态代理模式

4. 在各种BeanFactory以及ApplicationContext实现中也都用到模板 模式; 

3.为什么要使用 spring?

  • spring 提供 ioc 技术,容器会帮你管理依赖的对象,从而不需要自己 创建和 管理依赖对象了,更轻松的实现了程序的解耦。

  • spring 提供了事务支持,使得事务操作变的更加方便。

  • spring 提供了面向切片编程,这样可以更方便的处理某一类的问题。

  • 更方便的框架集成,spring 可以很方便的集成其他框架,比如 MyBatis、 hibernate 等。 

4.spring 常用的注入方式有哪 些?

  • setter 属性注入
  • 构造方法注入
  • 注解方式注入

5.spring 事务实现方式有哪些?

  • 声明式事务:声明式事务也有两种实现方式,基于 xml 配置文件的方式 和注 解方式(在类上添加 @Transaction 注解)。
  • 编码方式:提供编码的形式管理和维护事务。 

 

第十一天:

1.并发事务会带来哪些问题?

  1. 脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改, 而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据, 然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事 务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。

  2. 丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个 事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务 也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失 修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修 改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。

  3. 不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。 在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务 中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数 据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情 况,因此称为不可重复读。

  4. 幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务 (T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在 随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就 好像发生了幻觉一样,所以称为幻读。 

2.事务的隔离级别有哪些?

  1. READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交 的数据变更,可能会导致脏读、幻读或不可重复读。
  2. READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可 以阻止脏读,但是幻读或不可重复读仍有可能发生。
  3. REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致 的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻 读仍有可能发生。
  4. SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级 别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就 是说,该级别可以防止脏读、不可重复读以及幻读。 

3.说一下 spring mvc 运行流 程?

  • spring mvc 先将请求发送给 DispatcherServlet。
  • DispatcherServlet 查询一个或多个 HandlerMapping,找到处 理请求的 Controller。
  • DispatcherServlet 再把请求提交到对应的 Controller。
  • Controller 进行业务逻辑处理后,会返回一个 ModelAndView。
  • Dispathcher 查 询 一 个 或 多 个 ViewResolver 视 图 解 析 器 , 找 到 ModelAndView 对象指定的视图对象。
  • 视图对象负责渲染返回给客户端。 

4.spring mvc 有哪些组件? 

  • 前置控制器 DispatcherServlet。
  • 映射控制器 HandlerMapping。
  • 处理器 Controller。
  • 模型和视图 ModelAndView。
  • 视图解析器 ViewResolver。 

5.springmvc常见的注解 

  1. @Controller 作用在类上表示该类为控制层类 @RequestMapping用来处理请求地址映射的注解
  2. @PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数 上,即取出uri模板中的变量作为参数
  3. @requestParam主要用于在SpringMVC后台控制层获取参数值
  4. @ResponseBody该注解用于将Controller的方法返回的对象转换为json 格式
  5. @RequestBody用于接收前端传来的json实体,接收参数也是对应的实体 

第十二天:

1.MyBatis 中 #{}和 ${}的区别是 什么?

\#{}是预编译处理

,${}是字符替换。

在使用 #{}时,MyBatis 会将 SQL 中的 #{} 替换成“?”,配合 PreparedStatement 的 set 方法 赋值,这样可以有效的防止 SQL 注入, 保证程序的运行安全。 

2.什么地方使用${}

  • $的作用是字符拼接,不能防止sql注入,

  • 当使用${}参数作为字段名或表名 时使用。 比如: select * from ${tableName} 比如我要用${}在MyBatis的sql中拼接排序类型的时候 

3.当实体类的属性名和表中的字 段名不一致如何处理

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

通过<resultMap>类映射字段名和实体类属性名的一一对应的关系

4.MyBatis如何实现一对多

在resultMap中使用collection标签 

 

5.ResultType和ResultMap的 区别

1、resultmap:resultMap如果查询出来的列名和pojo的属性名不一 致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

2、resulttype:resultType使用resultType进行输出映射,只有查 询出来的列名和pojo中的属性名一致,该列才可以映射成功。

每日一更新,祝大家找到自己心仪的工作!!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值