一.javaSE
基础算法
一.斐波那契数列
逻辑:前两个数的值分别为 0 、1 或者 1、1;从第 3 个数字开始,它的值是前两个数字的和;
java递归代码实现
//定义斐波那契数列递归方式
// index 表示求数列中第 index 个位置上的数的值
public static int fibonacci(int index) {
// 设置结束递归的限制条件
if (index == 1 || index == 2) {
return 1;
}
// F(index) = F(index-1) + F(index-2)
return fibonacci(index - 1) + fibonacci(index - 2);
}
//斐波那契数列递归的 Java 程序
@Test
public void test1(){
// 输出前 10 个数
for (int i = 1; i <= 10; i++) {
System.out.print(fibonacci(i) + " ");
}
}
java数组代码实现
//斐波那契数列数组的Java程序
// index 表示求数列中第 index 个位置上的数的值
public static int fibonacci1(int index){
if(index < 0){
return -1;
}else if(index == 0){
return 0;
}else if(index == 1 || index == 2){
return 1;
}else{
int[] fibAry = new int[index+1];
fibAry[1] = 1;
fibAry[2] = 1;
for(int i = 3;i <= index;i++) {
fibAry[i] = fibAry[i - 1] + fibAry[i - 2];
}
return fibAry[index];
}
}
//斐波那契数列数组的Java程序调用
@Test
public void test2(){
// 输出前 10 个数
for (int i = 1; i <= 10; i++) {
System.out.print(fibonacci1(i)+" ");
}
}
二.完数
概念:各个小于它的约数(真约数,列出某数的约数,去掉该数本身,剩下的就是它的真约数)的和等于它本身的自然数叫做完全数(Perfect number),又称完美数或完备数。
java代码实现:
public static void main(String[] args) {
System.out.println("10000以内的完数如下:");
fun(10000);
}
//求完数:完数的定义:一个数恰好等于它的所有真因子之和
public static void fun(int n){
for (int i = 1; i <= n; i++) {
int factor = 0;//定义因子变量和,初始值为0
for (int j = 1; j < (i / 2) + 1; j++) {
if (i%j==0){
factor+=j;
}
}
if(factor == i){
System.out.println(i);
}
}
}
==和equals比较
==基本数据类型比较的是值的本身,引用类型比较的是堆中内存对象的地址值.
equals:object中默认为= = ,通常会重写
例子:
public class test {
public static void main(String[] args) {
String str1 = "hello"; //常量池地址
String str2 = new String("hello"); //堆中内存地址
String str3 = str2;
System.out.println(str1 == str2); //false
System.out.println(str1 == str3); //false
System.out.println(str2 == str3); //true
System.out.println(str1.equals(str2)); //true
System.out.println(str1.equals(str3)); //true
System.out.println(str2.equals(str3)); //true
}
}
JDK,JRE,JVM关系
java跨平台性的原理
.java文件经过javac工具编译为.class文件,java在不同版本中提供对应的jvm,由于我们的.class可以在
任意版本jvm中运行,使得我们一份.class文件能够在各种平台中运行
面向对象
什么是面向对象?
对比面向过程,是两种不同的处理问题的角度
面向过程更注重事情的每一个步骤以及顺序,面向过程更注重有哪些参与者(对象),各自需要做什么
比如:洗衣机洗衣服
面向过程会将任务拆分为一系列的步骤:1.打开洗衣机→2.放衣服→3.放洗衣粉→4.清洗→5.烘干
面向对象会拆分出人和洗衣机两个对象
人:打开洗衣机,放衣服,放洗衣粉
洗衣机:清洗,烘干
总结:面向过程比较简单直接,面向对象更易于复用,扩展和维护
封装
在于明确标识出允许外部使用的所有成员函数及属性
提供set,get方法对外访问,有效防止外部对其胡乱修改,具体细节由自身控制
继承
继承父类的方法,并做出自己的改变/或扩展
子类共性的方法或者属性直接使用父类的,实现了代码的复用性,只需扩展自己个性化的方法及属性
多态
基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同
条件:继承,重写,父类引用子类对象,无法调用子类的独有方法
父类类型 变量名 = new 子类对象
变量名.方法名();
集合(collection)
1.HashMap的底层数据结构是?
jdk1.8之前:
HashMap采用数组+链表结构结合在一起使用就是链表散列
Hash通过key的hashCode经过扰动函数处理后得到hash值,然后通过(n-1
) & hash 判断当前元素存放的位置(n指数据的长度),如果当前位置存在元素,
就判断该元素的hash值以及key值是否相等,相等则覆盖,如果不相同通过拉链
法解决冲突
扰动函数:就是HashMap中的hash方法,使用hash方法也就是扰动函数,是为了防止
一些实现比较差的hashcode方法,减少hash碰撞的次数.
jdk1.8之后:
当链表长度大于阀值(默认为8),会首先调用treefyBin()方法.这个方法会根据HashMap
数据来决定是否需要转换为红黑树.只有当数组长度大于或者等于64的情况下,才会执
行转换红黑树的操作,以减少搜索时间.否则,就是执行resize()方法对数组扩容.
java核心API
Web
Mybatis
什么是Mybatis
- MyBatis 是一款优秀的***持久层***框架,
- 它支持自定义 SQL、存储过程以及高级映射。
- MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
- MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO为数据库中的记录。
何如获取Mybatis
- Maven仓库
- Github
持久化
数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态的过程
- 内存:断电即失
- 数据库(JDBC),IO文件持久化
为什么要持久化 - 有一些对象,不能让他丢掉
- 内存太贵了
持久层
- Dao层,service层,controller层
- 完成持久化工作的代码块
- 层级界限十分明显
为什么需要Mybatis?
- 最重要一点:使用的人多
- 方便
- 帮助程序猿将数据存入数据库中
- 传统的JDBC太复杂,简化.框架,自动化
- 不用Mybatis也可以
- 优点
简单易学:
灵活:
sql和代码的分离,提高了可维护性。
提供映射标签,支持对象与数据库的orm字段关系映射。
提供对象关系映射标签,支持对象关系组建维护。
提供xml标签,支持编写动态sql。
构建一个Mybatis项目
1.创建Maven工程
2.导入依赖mysql,mybatis,junit
3.编写mybatis核心配置文件
4.编写工具类utils,获取SqlSession对象
public class SpringUtils {
private static SqlSessionFactory sqlSessionFactory;
static{
try{
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch (Exception e){
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
注意代码实现时:
当执行的是增删改的操作时,需要提交事务
<insert id="insert" parameterType="com.atguigu.pojo.User">
insert into mybatis.user values(#{id},#{name},#{pwd})
</insert>
提交事务代码实现:commit
public void insert(){
SqlSession sqlSession = SpringUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.insert(new User(3,"小花","123456"));
sqlSession.commit();
sqlSession.close();
}
错误分析
1.resource里面使用的是/连接
<mappers>
<mapper resource="com/atguigu/mapper/UserMapper.xml"/>
</mappers>
2.需要配置pom.xml
加载java中的properties,xml文件,默认不加载
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
万能Map
假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map
代码实现
//添加一个用户
int insert2(Map<String,Object> map);
<!--添加一个用户-->
<insert id="insert2" parameterType="map">
insert into mybatis.user(id,pwd) values(#{userid},#{userpwd})
</insert>
public void insert2(){
SqlSession sqlSession = SpringUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<String, Object>();
map.put("userid",4);
map.put("userpwd","123456");
mapper.insert2(map);
sqlSession.commit();
sqlSession.close();
}
Map传递参数,直接sql中取出key即可!【parameterType=“map”】
对象传递参数,直接sql中去对象的属性即可!【parameterType=“Object”】
只有一个基本类型的情况下,直接在sql中取到!
多个参数用Map,或者注解!
配置解析
1.核心配置文件
- mybatis-config.xml
- MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
2.环境配置(environments) - MyBatis 可以配置成适应多种环境
- 尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
- 学会配置多套运行环境
- Mybatis默认的事务管理器就是JDBC,连接池:POOLED
3.属性(properties) - 我们使用通过properties属性来实现引用配置文件
- 这些属性可以在外部进行配置,并可以进行动态替换
- 编写一个配置文件
- db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mysql?characterEncoding=UTF-8
username=root
password=root
- 在核心配置文件中引入
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="root"/>
</properties>
可以直接引入外部文件
可以在其中增加一些属性配置
如果两个文件有同一个字段,优先使用外部配置文件的!
4.类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写
方式一:
<!--可以给实体类起别名-->
<typeAliases>
<typeAlias type="com.atguigu.pojo.User" alias="User"/>
</typeAliases>
方式二: 每一个在包中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名
<typeAliases>
<package name="com.atguigu.pojo"/>
</typeAliases>
第一种可以DIY自定义别名,第二种不可以,如果非要改,在类上加注解@Alias(“user”)
5.设置(settings)
这是Mybatis中极为重要的调整设置,他们会改变Mybatis的运行是行为
7.映射器(mappers)
方式一:
<!--让每一个Mapper.xml都需要在Mybatis核心配置文件中注册-->
<mappers>
<mapper resource="com/atguigu/mapper/UserMapper.xml"/>
</mappers>
方式二:
<!--让每一个Mapper.xml都需要在Mybatis核心配置文件中注册-->
<mappers>
<mapper class="com.atguigu.mapper.UserMapper"/>
</mappers>
注意:
- 接口和它的映射文件必须同名
- 接口和他的映射文件必须在同一个包
方式三
<!--让每一个Mapper.xml都需要在Mybatis核心配置文件中注册-->
<mappers>
<package name="com.atguigu.mapper"/>
</mappers>
注意:
- 接口和它的映射文件必须同名
- 接口和他的映射文件必须在同一个包
6.作用域(Scope)和生命周期
生命周期和作用域是非常重要的,错误的使用会导致非常严重的***并发问题***
SqlSessionFactoryBuild
- 一旦创建了SqlSessionFactory,就不在需要它了
- 局部变量
SqlSessionFactory - 可以想象为数据库连接池
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
- SqlSessionFactory 的最佳作用域是应用作用域
- 最简单的就是使用单例模式或者静态单例模式
SqlSession - 连接到连接池的一个请求
- SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
- 打开一个 SqlSession,返回一个响应后,就关闭它
- 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中
- 这里的每一个Mapper就是一个具体的业务
解决属性名与字段名不一致问题
解决方法一:
- 起别名
<select id="selectAll" resultType="User">
select id,name,pwd as pwaaword from mybatis.user
</select>
解决方式二:resultMap
结果集映射
resultMap 元素是 MyBatis 中最重要最强大的元素。
ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
ResultMap 的优秀之处——你完全可以不用显式地配置它们。
原因:
数据库:id,name,pwd
实体类:id,name,password
<!--结果集映射-->
<resultMap id="UserMap" type="User">
<!--column数据库中的列,property实体类的属性-->
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="selectAll" resultMap="UserMap">
select * from mybatis.user
</select>
日志
- 日志工厂
如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的帮手
- SLF4J
- LOG4J【掌握】
- LOG4J2
- JDK_LOGGING
- COMMONS_LOGGING
- STDOUT_LOGGING【掌握】
- NO_LOGGING
在Mybatis中具体使用那个日志,在设置中设定
STDOUT_LOGGING的日志实现
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
具体的体现
Opening JDBC Connection
Created connection 937773018.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@37e547da]
==> Preparing: select * from mybatis.user
==> Parameters:
<== Columns: id, name, pwd
<== Row: 1, 小唐, 123456
<== Row: 2, 小王, 123456
<== Row: 3, 小花, 123456
<== Row: 4, null, 123456
<== Row: 5, null, 123456
<== Total: 5
User{id=1, name='小唐', password='123456'}
User{id=2, name='小王', password='123456'}
User{id=3, name='小花', password='123456'}
User{id=4, name='null', password='123456'}
User{id=5, name='null', password='123456'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@37e547da]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@37e547da]
LOG4J的日志实现
1.什么是log4j:
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件
我们也可以控制每一条日志的输出格式
通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程
可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
2.导入log4jMaven包
多对一处理
按照查询嵌套处理
<!--思路:
1.查询所有学生的信息
2.根据查询出来的学生的tid,寻找对应的老师!子查询
-->
<select id="getAllStudent" resultMap="StudentMap">
select * from student
</select>
<resultMap id="StudentMap" type="Student">
<!--复杂的属性我们需要单独处理 association 对象 collection 集合-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacherById"/>
</resultMap>
<select id="getTeacherById" resultType="Teacher">
select * from teacher where id = #{id}
</select>
按照结果嵌套查询处理
<select id="getAllStudent2" resultMap="StudentMap2">
SELECT s.id as tid,s.name as sname,t.name as tname
FROM teacher AS t,student AS s WHERE t.id=s.tid
</select>
<resultMap id="StudentMap2" type="Student">
<result property="id" column="tid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
一对多处理
按照结果嵌套处理
<select id="getTeacherById" resultMap="TeacherStudent">
SELECT t.id AS tid,t.name AS tname,s.id AS sid,s.name AS sname
FROM teacher AS t,student AS s WHERE t.id=s.tid
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"></result>
</collection>
</resultMap>
按照查询嵌套处理
<select id="getTeacherById2" resultMap="TeacherStudent2">
select * from teacher where id=#{id}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" column="id" ofType="Student" select="getStudentByTeacherId" javaType="ArrayList"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from student where tid=#{id}
</select>
小结:
- association 属性为对象时使用
- collection 属性为集合时使用
- javaType & ofType
- javaType 用来指定实体类中属性的类型
- ofType 用来指定映射到List或者集合中的pojo类型,泛型的约束类型
注意点:
- 保证sql的可读性,尽量保证通俗易懂
- 注意一对多和多对一中,属性名和字段的问题
- 如果问题不好排查,可以使用日志,建议使用log4j
动态SQL
什么是动态SQL:
动态SQL就是指根据不同的条件生成不同的SQL语句
所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,添加一些逻辑代码
if实例代码
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
choose、when、otherwise实例代码
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
缓存
查询数据库比较浪费资源,我们采用把数据存储在内存中,方便下次使用
缓存:
- 存在内存中的临时数据
- 解决高并发系统的性能问题
好处 - 减少和数据库的交互次数,减少系统开销,提高系统效率
使用情况 - 经常查询且不常改变的数据
一级缓存
一级缓存也叫本地缓存: sqlsession
- 与数据库同一次会话间查询到的数据会放在本地缓存中
- 以后如果需要获取相同的数据,直接从缓存中拿,没有必要去查数据库
测试步骤:
SpringMVC框架
spring框架
概述:spring是轻量级的管理Bean生命周期的框架,可以解决企业开发的负责性
特点:
(1)方便解耦,简化开发
(2)Aop编程
(3)方便与其他框架整合
(4)方便进行事务
(5)降低API开发
IOC
概念:控制反转,把对象的创建和对象之间的调用过程交给spring管理,
目的:为了耦合度降低
IOC底层原理:xml解析,工厂模式,反射
解析xml文件获取类的全路径,通过工厂模式,反射,class.newInstance()创建对象,并返回
IOC(接口):
1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
2.Spring提供IOC容器实现两种方式:
(1)BeanFactory:IOC容器基本实现,是Spring内部的接口,不提供开发人员进行使用
*加载配置文件不会创建对象,在获取对象的时候才去创建对象
(2)ApplicationContext:Beanfactory的子接口,提供更强大的功能,一般由开发人员使用
*加载配置文件时就会把配置文件对象进行创建
3.ApplicationContext实现类:
ClassPathXmlApplicationContext:相对路径src
FileSystemXmlAplicationComtext:绝对路径
4.bean管理基于xml方式创建对象
<bean id="唯一标识" class="类的全路径" ></bean>
4.1.bean管理基于xml方式创建对象并注入属性(set注入)
<bean id="唯一标识" class="类的全路径" >
<property name="属性名" value="属性值"></property>
</bean>
4.2.bean管理基于xml方式创建对象并注入属性(有参构造注入)
<bean id="唯一标识" class="类的全路径" >
<constructor-arg name="属性名" value="属性值"></constructor-arg>
</bean>
4.3.bean管理基于xml方式创建对象并注入其他类型属性属性(set注入)
属性注入空值
<property name="属性名">
<null></null>
</property>
属性注入特殊符号
<property name="属性名">
<value><![CDATA[<<南京>>]]></value>
</property>
4.4.bean管理基于xml方式创建对象并注入对象属性(set注入)
<!--service和dao对象的创建-->
<!--给service中的属性注入对象-->
<bean id="对象的唯一标识1" class="类的全路径" >
<property name="属性值" ref="对象的唯一标识2"></property>
</bean>
<bean name="对象的唯一标识2" class="类的全路径"></bean>
5.bean管理基于注解方式
5.1注解
(1)注解是代码特殊标记,格式@注解名(属性名=属性值,属性名=属性值…)
(2)注解的目的:简化开发
(3)注解的作用域:类,方法,属性
5.2.基于注解方式实现对象创建
(1)@Component
(2)@Service 常用在Service层
(3)@Controller 常用在Controller层
(4)@Repository 常用在Dao,Mapper层
作用一致,注解方式实现对象的创建.
5.3.基于注解方式实现属性对象的注入
(1)@Autowired 根据类型进行注入
(2)@Qualifier 根据名称进行注入,配合@Autowired一起使用
5.3.基于注解方式实现属性中基本属性的注入
@Value
5.4完全注解开发
创建配置类config,添加注解@Configuration,@ComponentScan(basePackages = {“包路径”})
加载配置类 AnnotationConfigApplicationContext(配置类.class)
Aop
概述:面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑
部分之间的***耦合度降低,提高程序的可重用性,提高了代码的开发效率.
通俗描述:不通过修改源代码方式,在主干工功能里面添加新功能
AOP底层原理:
1.动态代理
(1)有接口的情况→JDK动态代理
创建接口实现类的代理对象,增强类的方法
(2)没有接口的情况→CGLIB动态代理
AOP操作(AspectJ注解)
1.创建类,在类中定义方法
2.创建增强类(编写增强逻辑)
3.进行通知的配置
(1)在spring配置文件中,开启注解扫描
(2)使用注解创建类和增强类
(3)在增强类上面添加注解@Aspect
(4)在spring配置文件中开始生成代理对象
表示:所有的访问修饰符,包名下面的所有类,所有方法,任意参数
切入点表达式:execution( 包名..(…))
4.5种通知
前置,后置,异常,最终,环绕通知
环绕通知
@Around(@value = "切入点表达式")
public void around(ProceedingJoinPoint point){
执行被增强的方法
point.proceed();
}
5.公共切入点抽取
@Pointcut(@value = "切入点表达式")
public void pointdemo(){
}
(1)使用公共切入点
@Around(@value = "pointdemo()")
public void around(ProceedingJoinPoint point){
执行被增强的方法
point.proceed();
}
6.对同一个类的方法增强,使用注解@Order(数字)进行优先级判定,数字越小优先级越高
事务
事务是数据库中最小的单元,逻辑上一组操作,要么都成功,要么都失败
四大特性(ACID):
原子性:操作的最小单位,逻辑上一组操作,要么都成功,要么都失败
一致性:操作之前和操作之后,总量保持一直
隔离性:多事务操作时,不会产生影响
持久性:数据的修改是持久的
Spring事务管理
两种方式:编程式事务管理和声明式事务管理(建议使用)
声明式事务管理(底层使用AOP):
(1)基于注解方式(推荐使用)
(2)基于xml方式
Spring事务管理API
(1)提供一个接口,代表事务管理,这个接口针对不同的框架提供了不同的实现类
PlatformTransactionManager
(2)在类或者方法上添加注解@Transactional()
(3)@Transactional()中的相关参数
propagation:事务的传播行为
多事务方法之间的调用,这个过程中事务是如何管理的
事务方法:对数据库表数据进行变化的操作
Spring框架事务传播行为7种:
REQUIRED:如果方法本身有事务,调用其他方法之后,其他方法使用当前方法的里面的事务
如果方法本身没有事务,调用其他方法之后,创建新事务
REQUIRED_NEW:无论方法本身是否有事务,调用其他方法之后,创建新的事务
isolation:事务隔离级别
隔离性:多事务之间操作时不会产生影响,不考虑隔离性会出现很多问题
有3个问题:脏读,不可重复读,虚(幻)读
脏读:一个未提交的事务读取到另一个未提交事务的数据
不可重复读:一个未提交事务读取到另一个提交事务修改的数据
虚读:一个未提交的事务读取到另一个提交事务修改数据
解决问题的方式:
通过隔离级别,mysql默认使用repeatable read
timeout:超时时间
事务在一定时间内进行提交,如果不提交进行回滚
默认值是-1,不会超时,设置时间以秒为单位进行计算
readOnly:是否只读
默认值为false,修改为true时,只能进行查询操作
rollbackFor:回滚
设置出现哪些异常回滚
noRollbackFor:不回滚
设置出现哪些异常不回滚
SpringBoot
1.什么是springBoot
微服务
1.什么是微服务?
是一种架构风格
把一个项目拆分为多个服务,多个服务是独立运行,每个服务占用独立进程
Springcloud
1.什么是SpringCloud
springcloud并不是一种技术,是很多技术总称,很多框架的集合
springcloud里面有很多框架(技术),使用springcloud里面这些框架实现微服务的操作
springcloud,需要依赖springboot
2.springcloud版本依赖
参考网址:
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
3.什么是注册中心(nacos,Eureka,Zookeeper)
实现不同的微服务模块之间调用,把这些模块在注册中心进行注册,注册之后,实现互相调用
nacos:
comsumer(消费者)(调用方法) provider(生产者)(提供方法)
4.Feign
要求:必须在注册中心都注册,才能调用
5.Spring Cloud 在接口调用上,大致会经过哪些组件?
接口化请求调用→Fegin→Hystrix→Ribbon→http client
过程说明:在调用端创建接口,使用接口化请求调用(只是定义),Feign(服务发现)根据服务名字
找到对应的服务地址进行调用;Hystrix(熔断器),当服务端不能调用时,进行熔断;Ribbon(负载均衡)
,服务集群时负载均衡,http client(最终调用)
nginx
Redis
1.怎么解决事务冲突问题
悲观锁:采用锁机制,使数据只能一个线程操作,其他的必须排队,效率低
悲观锁:采用添加状态字段,多线程同时操作时,比较执行码是否一致,一致操作成功并
修改执行码(+1).
redis中采用watch监视一个或者多个key值,如果事务在执行之前这个(这些)key被其他
命令所改动,那么事务被打断.
2.事务的特点
操作指令:开启事务:multi 执行事务:exec 终止事务:discard
单独的隔离操作:事务中所有的命令序列化,按顺序执行.事务在执行过程中,不会被其他
客户端发来的命令所打断
没有隔离级别:队列中的命令没有提交之前,都不会实际执行,因为事务提交前任何指令都
不会被实际执行
不保证原子性:事务中如果有一条命令执行失败,其后的命令会被执行,没有回滚