spring

根据所画Spring图总结的重点

一、概念

1.spring是一个项目管理框架,同时也是一套Java EE解决方案

2.Spring是众多优秀设计模式的组合(工厂、单例、代理、适配器、包装器、观察者、模板、策略)

3.Spring并未替代现有框架产品,而是将众多框架进行有机整合,简化企业级开发,俗称"胶水框架"

二、山寨版IOC容器

解决的问题:service调用dao,原来的做法是自己new对象,当需要更改dao层的实现,只能更改编码. 从而实现对象间的解耦

主要类:MyClassPathXmlApplicaionContext

1.解析配置文件:把解析的信息封装到BeanDefinition.

得到bean的信息,把bean的信息封装到BeanDefinition,每个bean都会有自己的beanDefinition,把很多bean的beanDefinition放入一个map中.

2.通过反射创建对象:把对象放入对象池map中,此时放的是未给属性赋值的对象

从beansMap中获取bean的信息通过反射创建对象,将创建出来的对象放入objectMap

3.属性注入:通过反射调用对象的set方法,给对象的属性赋值

di:依赖注入,第二步创建的对象的属性时没有值的

三、Spring容器

1.BeanFactory:

IOC容器基本实现,时Spring内部的使用接口,不提供开发人员上进行使用.

加载配置文件时后不会创建对象,再获取对象(使用)才去创建对象.

public interface BeanFactory {
}

2.ApplicationContext

:BeanFactory接口的子接口,提供更多更强大的功能,一般有开发人员进行使用.

加载配置文件时候就会把在配置文件对象进行创建.

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory,HierarchicalBeanFactory,MessageSource,ApplicationEventPublisher, ResourcePatternResolver {
}

spring_第1张图片

  • ClassPathXmlApplicationContext:以xml的形式告诉容器管理那些bean
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
}
 //创建spring 容器,通过配置文件 beans1.xml 告知容器 要管理的 bean 有哪些
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans1.xml");
  • AnnotationConfigApplicationContext:以注解的形式告诉容器管理那些bean
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
}
//加载配置类 
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); 

3.IOC

3.1 什么是IOC

反转了依赖关系的满足方式,由之前的自己创建依赖对象,变成由工厂推送.(便主动为被动,即反转),解决了具有以来关系的组件之间的强耦合,使得项目形态更加稳健.

(1)IOC的概念:Inverse Of Controll:控制反转

控制反转,把对象创建和对象之间的调用过程,交给spring进行管理

(2)IOC的作用:为了降低耦合度

(3)IOC的底层实现:xml解析、工厂模式、反射

3.2 什么是DI

概念:在Spring创建对象的同时,为其属性赋值,称之为依赖注入

(1) set注入:创建对象时,spring工厂会通过Set方法为对象的属性赋值. bean中属性:

(2) 构造注入:bean中属性:

3.3 自动注入

也叫自动装配.根据装配规则(属性名和属性类型)spring自动将装配的属性值进行注入

  • byName:根据属性名称注入,注入值得bean的id和类的属性名一样
  • byType:根据属性类型注入,如果容器内有多个这个类型的bean,那么容器如果不知道注入哪一个,就会报错.

4.AOP

4.1 代理模式

(1) staticproxy: 通过代理类的对象,为原始类的对象(目标类的对象)添加辅助功能,更容易更换代理实现类,利于维护.

public class StaticProxyManager {
    public StaticProxyManager() {
    }
}
  • 代理类=实现原始类相同接口+添加辅助功能+调用原始类的业务方法.

  • 静态代理的问题:

    • 代理类数量过多,不利于项目的管理.

    • 多个代理类的辅助功能代码冗余,修改时维护性差.

房子,房主,中介,租客

(2) jdkproxy: 代理对象和真实对象的关系,像是兄弟.代理对象对真实对象进行增强

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
}

封装一个工具类,实现 InvocationHandler 接口,进行重写 getProxy 和 invoke 方法.

(3) cglibproxy: 代理对象和真实对象的关系,就像是父子.是子类对象对父类对象的增强

class CglibAopProxy implements AopProxy, Serializable {
}

4.2 什么是AOP

(1) AOP的概念

即面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使业务逻辑的各部分之间耦合度降低,提高程序的可重用性,提好了开发效率,通俗的讲,可以实现不修改源代码的方式,在核心业务里面添加新的功能

(2) AOP的作用

Spring的AOP编程即是通过动态代理类为原始类的方法添加辅助功能

(3) AOP的底层实现

AOP底层的原理就是动态代理,真正干活bean使代理bean,代理bean对真实bean功能增强

4.3 SpringAop的相关概念

1 切点(Pointcut):真正要被增强的方法

@Pointcut(value = "execution(* delete(..))")
    public void point2(){
        System.out.println("切点2");
    }

2 通知(Advice): 增强的业务代码.可以为切入点添加额外功能,分为:

​ (1) 前置通知:

前置通知继承org.springframework.aop.MethodBeforeAdvice;
@Before("point1()")
    public void before(){
        System.out.println("基于aspectj注解形式的前置通知,要求大家掌握");
    }

​ (2) 后置通知:

后置通知继承org.springframework.aop.AfterReturningAdvice;
@After("point2()")
    public void after(){
        System.out.println("基于aspectj注解形式的后置通知,要求大家掌握");
    }

​ (3) 环绕通知:

环绕通知继承org.aopalliance.intercept.Methodlnterceptor;
@Around("point2()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前置");

        Object result = joinPoint.proceed();
        System.out.println("环绕后置");
        System.out.println(result);
        return result;
    }

​ (4) 异常通知:

异常通知继承org.springframework.aop.ThrowsAdvice;
@AfterThrowing(value = "point2()",throwing = "ex")
    public void afterthrowing(Exception ex){

        System.out.println("异常通知");
        System.out.println("异常信息:"+ ex.getMessage());
    }

​ (5) 最终通知.

@AfterReturning("point2()")
    public void afterreturning(){
        //切点正常执行 没有异常 才会执行 最终通知
        System.out.println("最终通知");
    }

3 切面(Aspect): 切点 + 通知

结果先执行前置通知.但随着spring版本的不同,下面各个通知类的执行结果顺序并不相同 . 但是异常通知只有在出现异常是才会执行.

5.实现方式

1 Schema-based(了解)

定义通知类(添加额外通知) , 定义bean标签 , 定义切入点(PointCut)形成切面(Aspect)

2 AspectJ

​ (1) xml配置形式

​ 创建通知类 , xml配置 , 测试

​ (2) 注解形式

​ 配置文件


    
    <context:component-scan base-package="com.qf">context:component-scan>

    
    <aop:aspectj-autoproxy>aop:aspectj-autoproxy>

通知类

@Aspect    // 当前类 是一个 切面类
@Component    // 这个注解 表明 当前类的对象 是spring 管理的bean
public class AspectJAnnoAdvice {

    // @Before 表示前置通知
    //@Before("execution(* save(..))")
    //public void before(){
    //    System.out.println("基于aspectj注解形式的前置通知,要求大家掌握");
    //}

    @Pointcut(value = "execution(* save(..))")
    public void point1(){
        System.out.println("切点1");
    }

    @Pointcut(value = "execution(* delete(..))")
    public void point2(){
        System.out.println("切点2");
    }

    @Before("point1()")
    public void before(){
        System.out.println("基于aspectj注解形式的前置通知,要求大家掌握");
    }
    
    @After("point2()")
    public void after(){
        System.out.println("基于aspectj注解形式的后置通知,要求大家掌握");
    }
    
    @Around("point2()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前置");
        Object result = joinPoint.proceed();
        System.out.println("环绕后置");
        System.out.println(result);
        return result;
    }


    @AfterReturning("point2()")
    public void afterreturning(){
        //切点正常执行 没有异常 才会执行 最终通知
        System.out.println("最终通知");
    }

    @AfterThrowing(value = "point2()",throwing = "ex")
    public void afterthrowing(Exception ex){
        System.out.println("异常通知");
        System.out.println("异常信息:"+ ex.getMessage());
    }
}

四、注解

1. 四个创建bean的注解

(1) @Component : 通用

@Component
public class App {
}

(2) @Service : 业务层专用

@Service(value = "userService")
public class UserServiceImpl implements UserService {
}

(3) @Controller : web层(Controller层)专用

@Controller
@RequestMapping("/hello") // 访问路径,等价于url-pattern
public class HelloController {
}

(4) @Repository : dao层专用

@Repository
public class UserJdbcDaoImpl implements UserDao {
}

这四个注解功能是一样的,都可以用来创建bean实例

2. 注入依赖bean的注解

(1) @Autowired: 现根据类型注入,再根据名字注入

​ @Qualifier: 根据名称进行注入

@Autowired  
@Qualifier(value = "userDaoImpl1")
private UserDao userDao;     

(2) @Resource: 先根据名字注入,再根据类型注入

@Resource(name = "userDaoImpl1") //根据名称进行注入 
private UserDao userDao; 

3 注入普通属性的注解

@Value: 注入普通属性的注解

@Value(value = "abc") 
private String name;

4 标识配置类的注解

@configuration: 替代xml配置文件

@Configuration //作为配置类,替代 xml 配置文件 
@ComponentScan(basePackages = {"com.glls"}) 
public class SpringConfig { 
} 

5 指定扫描包的注解

@ComponentScan(basePackages = {“com.hui”})

6 指定优先级的注解

@Primary

7 指定初始化方法的注解

@PostConstruct

8 指定销毁bean的时候调用的注解

@PreDestory

9 指定作用域的注解

@Scope : 用户控制bean的创建模式

10 切面类的注解

(1) @Aspect : 声明此类是一个切面类,会包含切入点(pointcut)和通知(advice)

@Aspect // 声明此类是一个切面类:会包含切入点(pointcut)和通知(advice)
@Component //声明组件,进入工厂
public class MyAspect {
}

(2) @Pointcut : 定义切入点

@Pointcut(value = "execution(* delete(..))")
public void point2(){
    System.out.println("切点2");
}

五、SM整合

1 spring和mybatis整合的中间依赖

添加依赖 如附代码1

2 spring的配置文件

(1) 准备数据原配置文件 db.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
jdbc.username=root
jdbc.password=123456

(2) applicationContext.xml

​ 附代码2

3 mybatis配置文件




    
        
        
    
    
        
        
    

4 logback日志的配置文件

(1) 添加依赖

(2) logback.xml

​ 附代码3

六、事务

1 事务的概念

事务是数据库操作的基本单元,逻辑上的一组操作,要么都成功,要么都失败.也就是说只要一组操作中有一个失败了,那么这组操作都失败

2 事务的特性

ACID

(1) A:atomicity,原子性.一组操作整体不可拆分,要么都成功,要么都失败.

(2) C:consistency,一致性.数据在十五的前后哦,业务整体一致

(3) I:isolation,隔离性.事务之间,互相隔离

(4) D:durability,持久性.一旦事务执行成功,数据一定会落盘在数据库

3 事务的隔离级别

(1) isolation:隔离级别

名称 描述
default (默认值)(采用数据库的默认的设置) (建议)
read-uncommited 读未提交
read-commited 读已提交 (Oracle数据库默认的隔离级别)
repeatable-read 可重复读 (MySQL数据库默认的隔离级别)
serialized-read 序列化读

隔离级别由低到高为:read-uncommited < read-commited < repeatable-read < serialized-read

(2) 事务并发时的安全问题

问题 描述
脏读 一个事务读取到另一个事务还未提交的数据。大于等于 read-commited 可防止
不可重复读 一个事务内多次读取一行数据的相同内容,其结果不一致。大于等于 repeatable-read 可防止
幻影读 幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。mysql 幻读的详解、实例及解决办法 - SegmentFault 思否

(3) 数据库事务的操作.

附代码4

4 在spring环境中基于注解来管理事务

(1) 配置事务管理器.在applicationContext2.xml 中配置基于注解的事务DataSourceTransactionManager

事务管理器,其中持有DataSource,可以控制事务功能(commit,rollback等).

注意:DataSourceTransactionManager 和 SqlSessionFactoryBean 要注入同一个DataSource的Bean,否则事务控制失败!!!


<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource">property>
bean>

(2) 开启事务的注解


    <tx:annotation-driven transaction-manager="tx"/>

(3) 在需要事务的方法上使用注解

@Transactional
public void transferMoney(int from, int to, double money) {
   ......
}

(4) 注解

    //@Transactional(isolation = Isolation.SERIALIZABLE)  // 序列化读的隔离级别 可以避免脏读  不可重复读  幻读
    @Transactional(isolation = Isolation.REPEATABLE_READ)  // 可重复读的隔离级别 可以避免脏读  不可重复读   但是会出现 幻读
    //@Transactional(isolation = Isolation.READ_COMMITTED)  // 读已提交的隔离级别 可以避免脏读  但是会出现 不可重复读  幻读
    //@Transactional(isolation = Isolation.READ_UNCOMMITTED)  // 读未提交的隔离级别 会出现脏读  不可重复读  幻读
    public List<Order> findOrderById(Integer id) {

        List<Order> list1 = orderMapper.findOrderByUserId(id);
        System.out.println(list1);

        System.out.println("----------------------");

        List<Order> list2 = orderMapper.findOrderByUserId(id);
        return list1;
    }

面试题:

  1. 单例bean和多例bean的区别(默认是单例bean)

  2. BeanFactory:是一个容器接口,是一个容器

    FactoryBean:是一个bean,即工厂bean,产生bean的bean

spring中 当有 切面时 使用的bean 是动态代理对象,是在BeanPostProcessor bean的处理器方法的后置增强方法 替换的

3.spring 在生成动态代理对象时优先选择哪种方式–>jdk的方式

附代码1



<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0modelVersion>

  <groupId>com.glls.java2301groupId>
  <artifactId>smartifactId>
  <version>1.0-SNAPSHOTversion>
  <packaging>warpackaging>

  <name>sm Maven Webappname>
  
  <url>http://www.example.comurl>

  <properties>
    <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    <maven.compiler.source>1.8maven.compiler.source>
    <maven.compiler.target>1.8maven.compiler.target>
  properties>

  <dependencies>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-contextartifactId>
      <version>5.2.9.RELEASEversion>
    dependency>

    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-aspectsartifactId>
      <version>5.2.9.RELEASEversion>
    dependency>

    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>4.12version>
    dependency>

    <dependency>
      <groupId>org.projectlombokgroupId>
      <artifactId>lombokartifactId>
      <version>1.18.12version>
    dependency>

    <dependency>
      <groupId>mysqlgroupId>
      <artifactId>mysql-connector-javaartifactId>
      <version>8.0.18version>
    dependency>
    
    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatisartifactId>
      <version>3.4.6version>
    dependency>

    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-jdbcartifactId>
      <version>5.2.9.RELEASEversion>
    dependency>

    
    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatis-springartifactId>
      <version>1.3.2version>
    dependency>

    
    <dependency>
      <groupId>com.alibabagroupId>
      <artifactId>druidartifactId>
      <version>1.1.16version>
    dependency>

    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webartifactId>
      <version>5.2.9.RELEASEversion>
    dependency>

    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>javax.servlet-apiartifactId>
      <version>3.1.0version>
      <scope>providedscope>
    dependency>

    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>jsp-apiartifactId>
      <version>2.0version>
      <scope>providedscope>
    dependency>

    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>jstlartifactId>
      <version>1.2version>
    dependency>

    
    <dependency>
      <groupId>org.slf4jgroupId>
      <artifactId>slf4j-apiartifactId>
      <version>1.7.25version>
    dependency>
    <dependency>
      <groupId>ch.qos.logbackgroupId>
      <artifactId>logback-coreartifactId>
      <version>1.2.3version>
    dependency>
    <dependency>
      <groupId>ch.qos.logbackgroupId>
      <artifactId>logback-classicartifactId>
      <version>1.2.3version>
    dependency>
    <dependency>
      <groupId>log4jgroupId>
      <artifactId>log4jartifactId>
      <version>1.2.17version>
    dependency>
    <dependency>
      <groupId>org.logback-extensionsgroupId>
      <artifactId>logback-ext-springartifactId>
      <version>0.1.4version>
    dependency>
  dependencies>

  <build>
    <finalName>smfinalName>
    <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-clean-pluginartifactId>
          <version>3.1.0version>
        plugin>
        
        <plugin>
          <artifactId>maven-resources-pluginartifactId>
          <version>3.0.2version>
        plugin>
        <plugin>
          <artifactId>maven-compiler-pluginartifactId>
          <version>3.8.0version>
        plugin>
        <plugin>
          <artifactId>maven-surefire-pluginartifactId>
          <version>2.22.1version>
        plugin>
        <plugin>
          <artifactId>maven-war-pluginartifactId>
          <version>3.2.2version>
        plugin>
        <plugin>
          <artifactId>maven-install-pluginartifactId>
          <version>2.5.2version>
        plugin>
        <plugin>
          <artifactId>maven-deploy-pluginartifactId>
          <version>2.8.2version>
        plugin>
      plugins>
    pluginManagement>

    
    <resources>
      <resource>
        <directory>src/main/javadirectory>
        <includes>
          <include>**/*.xmlinclude>
        includes>
      resource>
      <resource>
        <directory>src/main/resourcesdirectory>
        <includes>
          <include>**/*.xmlinclude>
          <include>**/*.propertiesinclude>
          <include>**/*.iniinclude>
        includes>
      resource>
    resources>
  build>
project>

附代码2


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    
    
    <context:component-scan base-package="com.glls.java2301">context:component-scan>
    
    <aop:aspectj-autoproxy>aop:aspectj-autoproxy>
    
    <context:property-placeholder location="classpath:db.properties" />
	
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        
        <property name="maxWait" value="60000"/>
        
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        
        <property name="minEvictableIdleTimeMillis" value="300000"/>
    bean>

    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        
        <property name="dataSource" ref="dataSource">property>
        
        <property name="configLocation" value="classpath:mybatis-config.xml">property>
    bean>
    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        
        <property name="basePackage" value="com.glls.java2301.mapper">property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">property>
    bean>
beans>

附代码3


<configuration>
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <Target>System.outTarget>
        <Encoding>UTF-8Encoding>
        <encoder>
            <pattern>%d{yyyy-MM-dd_HH:mm:ss.SSS} %5p [%t] [%c{1}]:%L - %m%n
            pattern>
        encoder>
    appender>
    <appender name="logfile"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <Encoding>UTF-8Encoding>
        <encoder>
            <pattern>%d %p [%t] [%c]:%L - %m%npattern>
        encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUGlevel>
        filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>log/%d{yyyy-MM-dd-HH'.log'}fileNamePattern>
        rollingPolicy>
    appender>
    <logger name="org.springframework" level="WARN" />
    <logger name="org.springframework.remoting" level="WARN" />
    <logger name="org.springframework.scheduling.quartz" level="WARN" />
    <logger name="org.springframework.data.jpa" level="DEBUG" />
    <logger name="org.cometd" level="WARN" />
    <logger name="ch.qos.logback" level="WARN" />
    <logger name="com.springapp.mvc" level="DEBUG" />
    <logger name="com.glls.java2301.mapper" level="DEBUG">logger>
    

    <root level="ERROR">
        <appender-ref ref="stdout" />
        <appender-ref ref="logfile" />
    root>
configuration>

附代码4

SELECT @@tx_isolation;       --  查看 当前 隔离级别

SHOW VARIABLES LIKE 'autocommit'  --  查看自动提交 是否开启

SET autocommit=0;    --  关闭自动提交 
 
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;   -- 设置 读未提交 隔离级别    会出现脏读 不可重复度 幻读
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;   -- 设置 读已提交 隔离级别  可出现 不可重复度 幻读
SET SESSION TRANSACTION ISOLATION LEVEL READ REPEATABLE READ;   -- 设置 可重复度 隔离级别  可出现幻读

#步骤1
START TRANSACTION;  -- 开启事务

UPDATE t_order  SET productNum = 3 WHERE userId = 10;

#步骤3 
-- 提交  或者  回滚
COMMIT;     -- 提交事务
ROLLBACK;   -- 回滚事务

vel=“DEBUG” />


    
    

```

附代码4

SELECT @@tx_isolation;       --  查看 当前 隔离级别

SHOW VARIABLES LIKE 'autocommit'  --  查看自动提交 是否开启

SET autocommit=0;    --  关闭自动提交 
 
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;   -- 设置 读未提交 隔离级别    会出现脏读 不可重复度 幻读
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;   -- 设置 读已提交 隔离级别  可出现 不可重复度 幻读
SET SESSION TRANSACTION ISOLATION LEVEL READ REPEATABLE READ;   -- 设置 可重复度 隔离级别  可出现幻读

#步骤1
START TRANSACTION;  -- 开启事务

UPDATE t_order  SET productNum = 3 WHERE userId = 10;

#步骤3 
-- 提交  或者  回滚
COMMIT;     -- 提交事务
ROLLBACK;   -- 回滚事务

你可能感兴趣的:(Java第三阶段,spring,java,后端)