@[TOC]目录
1. spring事务
事务简介
事务在逻辑上是一组操作,要么执行,要不都不执行。主要是针对数据库而言的,比如说 MySQL。
为了保证事务是正确可靠的,在数据库进行写入或者更新操作时,就必须得表现出 ACID 的 4 个重要特性:
原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
事务隔离(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
其中,事务隔离又分为 4 种不同的级别,包括:
读未提交(Read uncommitted),最低的隔离级别,允许“脏读”(dirty reads),事务可以看到其他事务“尚未提交”的修改。如果另一个事务回滚,那么当前事务读到的数据就是脏数据。
读已提交(read committed),一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。
可重复读(repeatable read),一个事务可能会遇到幻读(Phantom Read)的问题。幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。
串行化(Serializable),最严格的隔离级别,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。虽然 Serializable 隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。如果没有特别重要的情景,一般都不会使用 Serializable 隔离级别。
需要格外注意的是:事务能否生效,取决于数据库引擎是否支持事务,MySQL 的 InnoDB 引擎是支持事务的,但 MyISAM 就不支持。
spring事务
Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spring 是无法提供事务功能的。Spring 只提供统一事务管理接口,具体实现都是由各数据库自己实现,数据库事务的提交和回滚是通过数据库自己的事务机制实现。
Spring 支持编程式事务管理和声明式事务管理两种方式:
后者最常见,通常情况下只需要一个 @Transactional 就搞定了
1.编程式事务
编程式事务管理使用 TransactionTemplate,需要显式执行事务。
编程式事务是指将事务管理代码嵌入嵌入到业务代码中,来控制事务的提交和回滚。
就编程式事务管理而言,Spring 更推荐使用 TransactionTemplate。
在编程式事务中,必须在每个业务操作中包含额外的事务管理代码,就导致代码看起来非常的臃肿,但对理解 Spring 的事务管理模型非常有帮助。
声明式事务
声明式事务管理建立在 AOP 之上的。其本质是通过 AOP 功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前启动一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务
优点是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过 @Transactional 注解的方式,便可以将事务规则应用到业务逻辑中,减少业务代码的污染。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
**1. 编程式事务 当系统需要明确的,细粒度的控制各个事务的边界,应选择编程式事务。
- 声明式事务 当系统对于事务的控制粒度较粗时,应该选择声明式事务,通过标签和切面形式在xml中进行配置。**
spring中的事务隔离级别
脏读、不可重复读、幻象读概念说明:
a.脏读:指当一个事务正字访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。
b.不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。
c.幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)
2.spring特性有哪些
Spring框架是一个强大而灵活的Java开发框架,具有以下主要特性:
-
轻量级和非侵入性:Spring框架采用轻量级设计,不依赖于任何特定的容器或服务器。它可以与其他框架和库无缝集成,并且没有硬性规定的代码结构。
-
控制反转(IoC):Spring通过控制反转实现了松耦合的组件之间的依赖关系管理。它将对象的创建和依赖注入交给了Spring容器来管理,通过配置文件或注解来描述组件之间的关系。
-
面向切面编程(AOP):Spring提供了AOP支持,使得开发者能够将应用程序的关注点(例如日志记录、事务管理等)与核心业务逻辑分离,提高代码的可维护性和复用性。
面向切面编程(AOP):Spring 支持面向切面编程,可以用来实现功能的横切,比如日志记录、性能统计、安全检查等。 -
容器管理:Spring框架提供了一个容器来管理和配置Java对象的生命周期以及依赖关系。这个容器可以在应用程序中加载并管理bean,实现了对象的创建、初始化、销毁和依赖注入等功能。
-
数据访问支持:Spring框架提供了对各种数据访问技术的支持,包括JDBC、ORM框架(如Hibernate、MyBatis)、JPA等。它简化了数据访问层的开发,提供了事务管理、连接池和异常处理等功能。
-
MVC框架:Spring框架提供了一个灵活的MVC框架,用于构建Web应用程序。它基于**模型-视图-控制器(MVC)**设计模式,通过分离业务逻辑和展示逻辑,使得Web应用程序的开发更加简单和可维护。
-
安全性:Spring框架提供了全面的安全性支持,包括认证、授权、加密和访问控制等它可以集成到各种应用中,保护应用程序免受潜在的攻击和威胁。
总结起来,Spring框架具有轻量级、非侵入性、IoC、AOP、容器管理、数据访问支持、MVC框架和安全性等重要特性,使得Java开发变得更加简单、高效和可扩展。
3.什么是AOP
实现AOP的技术,主要分为两大类:
一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
AOP(面向切面编程)是一种编程范式,旨在通过将横切关注点(Cross-cutting Concerns)与核心业务逻辑分离,来提高代码的可维护性和复用性。
在传统的面向对象编程中,程序的功能被组织成一个个类和方法。然而,某些功能并不只属于单个类或方法,它们跨越多个类和方法,称为横切关注点。例如,日志记录、事务管理、安全性检查等都是横切关注点。这些横切关注点通常散布在整个应用程序中,导致代码的重复和耦合性增加。
AOP通过将这些横切关注点从核心业务逻辑中分离出来,以模块化的方式进行管理。它通过在程序执行过程中动态地将额外的功能(称为切面)织入到横切关注点所在的位置上,实现了对核心业务逻辑的增强。这样,我们就可以将这些横切关注点的实现逻辑放在一个或多个切面中,而不需要在每个类或方法中重复编写相同的代码。
AOP的核心概念包括切面(Aspect)、连接点(Join Point)、切点(Pointcut)、通知(Advice)和织入(Weaving)等:
- 切面(Aspect):一个切面是一个模块,包含了横切关注点的实现逻辑。
- 连接点(Join Point):程序执行过程中的一个特定点,例如方法调用或异常抛出。
- 切点(Pointcut):用于定义哪些连接点将被切面处理。它可以通过表达式或注解来指定。
- 通知(Advice):在切点位置上执行的额外功能,包括前置通知、后置通知、异常通知、返回通知和环绕通知等。
- 织入Weaving):将切面应用到目标对象并创建新的代理对象的过程。
AOP可以与各种编程语言和框架结合使用,例如Java中的Spring框架和.NET中的AspectJ。它提供了一种灵活、可重用和模块化的方式来处理横切关注点,使得代码更加清晰、可维护和可测试。
4. 在项目中使用了哪些注解
1、@Controller:用于标注控制器层组件
2、@Service:用于标注业务层组件
3、@Component : 用于标注这是一个受 Spring 管理的组件,组件引用名称是类名,第一个字母小写。可以使用@Component(“beanID”) 指定组件的名称
4、@Repository:用于标注数据访问组件,即DAO组件
5、@Bean:方法级别的注解,主要用在@Configuration和@Component注解的类里,@Bean注解的方法会产生一个Bean对象,该对象由Spring管理并放到IoC容器中。引用名称是方法名,也可以用@Bean(name = “beanID”)指定组件名
6、@Scope(“prototype”):将组件的范围设置为原型的(即多例)。保证每一个请求有一个单独的action来处理,避免action的线程问题。
由于Spring默认是单例的,只会创建一个action对象,每次访问都是同一个对象,容易产生并发问题,数据不安全。
7、@Autowired:默认按类型进行自动装配。在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
8、@Resource:默认按名称进行自动装配,当找不到与名称匹配的Bean时会按类型装配。
简单点说,就是,能够明确该类是一个控制器类组件的,就用@Controller;能够明确是一个服务类组件的,就用@Service;能够明确该类是一个数据访问组件的,就用@Repository;不知道他是啥或者不好区分他是啥,但是就是想让他动态装配的就用@Component。
@Controller、@Service、@Component、@Repository都是类级别的注解,如果一个方法也想动态装配,就用@Bean。
当我们想按类型进行自动装配时,就用@Autowired;当我们想按名称(beanID)进行自动装配时,就用@Resource;当我们需要根据比如配置信息等来动态装配不同的组件时,可以用getBean(“beanID”)。
5. 在项目中是否使用过mybatis
- Myba是一款优秀的持久层框架
- MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程,减少了代码的冗余,减少程序员的操作。
- MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 实体类 【Plain Old Java Objects,普通的 Java对象】映射成数据库中的记录。
6.mybaitis使用#和$的区别
#占位符的特点
-
MyBatis处理 #{ } 占位符,使用的 JDBC 对象是PreparedStatement 对象,执行sql语句的效率更高。
-
使用PreparedStatement 对象,能够避免 sql 注入,使得sql语句的执行更加安全。
-
#{ } 常常作为列值使用,位于sql语句中等号的右侧;#{ } 位置的值与数据类型是相关的。
$占位符的特点
-
MyBatis处理 ${ } 占位符,使用的 JDBC 对象是 Statement 对象,执行sql语句的效率相对于 #{ } 占位符要更低。
-
${ } 占位符的值,使用的是字符串连接的方式,有 sql 注入的风险,同时也存在代码安全的问题。
-
${ } 占位符中的数据是原模原样的,不会区分数据类型。
-
${ } 占位符常用作表名或列名,这里推荐在能保证数据安全的情况下使用 ${ }。
(1)$作用相等于是字符串拼接
(2)#作用相当于变量值替换
7. java的集合
Collection 接口的接口 对象的集合(单列集合)
├——-List 接口:元素按进入先后有序保存,可重复
│—————-├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
│—————-├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
│—————-└ Vector 接口实现类 数组, 同步, 线程安全
│ ———————-└ Stack 是Vector类的实现类
└——-Set 接口: 仅接收一次,不可重复,并做内部排序
├—————-└HashSet 使用hash表(数组)存储元素
│————————└ LinkedHashSet 链表维护元素的插入次序
└ —————-TreeSet 底层实现为二叉树,元素排好序
Map 接口 键值对的集合 (双列集合)
├———Hashtable 接口实现类, 同步, 线程安全
├———HashMap 接口实现类 ,没有同步, 线程不安全-
│—————–├ LinkedHashMap 双向链表和哈希表实现
│—————–└ WeakHashMap
├ ——–TreeMap 红黑树对所有的key进行排序
└———IdentifyHashMap
8.list的插入时间复杂度
9.map的插入时间复杂度
10.对于后端的理解
11.抽象类和接口的区别
实例化:抽象类不能被直接实例化,只能作为父类被继承。子类需要继承抽象类并实现其中的抽象方法,才能创建实例。接口也不能被直接实例化,但是可以通过实现接口的类来实例化。
①抽象类可以定义构造器但接口不行;
②抽象类里面可以定义抽象方法也可以定义具体方法,但**接口里面只能定义抽象方法;**不能实现方法
③一个类可以实现多个接口但只能继承一个抽象类;
④接口中不能有静态方法,且定义的变量均为常量,抽象类中可以有静态方法且可以定义成员变量;
⑤接口中的方法必须是public的,而抽象类可以有其它属性;
12.接收请求参数的方法有哪些
后端接收参数的几种方式和注解
第一种:@RequestParam注解
作用:将指定的请求参数赋值给方法中的形参。
接收形式:Get传参请求
属性:
1、value:绑定请求的参数名,默认绑定为同名的形参。
2、required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报错。
3、defaultValue:默认值,表示如果请求中没有接收到值时的默认值。
用法示例:
@GetMapping("/test")
public void test(@RequestParam(required = true)String name,@RequestParam(defaultValue = "20")Integer age) {
System.out.println("name:"+name+",age:"+age);
}
@RestController
public class UserController {
@GetMapping("/user")
public String getUserInfo(@RequestParam("username") String username,
@RequestParam("password") String password){
return username+"\n"+password;
}
}
第二种:@PathVariable注解
作用:接收请求路径中占位符的值。
接收形式:Get路径请求。
属性:value:String类型,绑定请求的参数名,默认绑定为同名的形参。
用法示例
@GetMapping("/selectOne/{id}")
public void test(@PathVariable Integer id) {
System.out.println("id:"+id);
}
第三种:@RequestBody注解
作用:接收前端传递的Json对象的字符串
接收形式:Post请求
示例
@PostMapping("/test")
public void test(@RequestBody User user){
System.out.println("user:"+user);
}