Java - 事务

目录

一、概述

事务定义:

事务特性:ACID

并发访问问题(隔离问题):

隔离级别: 用于解决隔离问题。

 常见数据库默认隔离级别:

性能&安全:

二、MyBatis事务操作

操作基础代码:

转账的流程:

创建表:

准备工作:

具体操作:

SqlMapConfig.xml:

pom.xml中所需坐标:

Account类:

AccountMapper接口:

MybatisUtils类:

TestAccount类:


一、概述

事务定义:

在一组业务逻辑(ABCD)中,要么全部成功,要么全部失败。

事务特性:ACID
  • 原子性:事务是一个原子操作单元,其对数据的修改要么全部执行,要么全不执行。
  • 一致性:事务必须使数据库从一个一致性状态变换到另一个一致性状态。
  • 隔离性:多个事务并发执行时,一个事务的执行不应影响其他事务。
  • 持久性:一旦事务提交,则其修改的效果就是永久性的。
并发访问问题(隔离问题):
  • 脏读:一个事务读到了另一个事务没有提交的数据。
  • 不可重复读:一个事务读到了另一个事务已经提交的数据(特质Update)。
  • 虚读/幻读:一个事务读到了另一个事务已经提交的数据(特指Insert)。 -- 纯理论       
隔离级别: 用于解决隔离问题。
  • 读未提交:最低级别的隔离,一个事务可以看到其他还未提交的事务的数据。
  • 读已提交:一个事务只能看到已经提交的事务所做的更改。
  • 可重复读:保证同一事务中多次读取的数据是一致的。
  • 串行化:最高级别的隔离,事务串行执行,可以避免脏读、不可重复读、幻读问题。

 常见数据库默认隔离级别:
  • mysql:默认基本可重复读
  • oracle:默认基本读已提交
性能&安全:
  • 性能:读未提交> 读已提交> 可重复读 > 串行化
  • 安全:读未提交< 读已提交< 可重复读 < 串行化  

二、MyBatis事务操作

操作基础代码:
SqlSession sqlSession = null;
try {
    //1 开始事务,默认关闭自动提交,言外之意开启事务

    // 操作
    // 更新语句付款;
    // 更新语句收款;

    //2 提交事务
    sqlSession.commit();
} catch (Exception e) {
    //3 回滚事务
    sqlSession.rollback();
} finally {
    //4 释放资源
    sqlSession.close();
}
转账的流程:

创建表:
create table account(
	id int primary key auto_increment,
	name varchar(10),
	money int 
);

insert into account(id,name,money) values(null,'jack',100);
insert into account(id,name,money) values(null,'rose',0);
准备工作:

具体操作:
SqlMapConfig.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <settings>
        <!--在控制台输出发送的sql日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>

            <!--目前只关注这部分内容,它的作用就是声明要连接的数据信息-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/day25"/>
                <property name="username" value="root"/>
                <property name="password" value="25692569"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--声明含有sql的接口所在包-->
        <package name="com.czxy.mapper"/>
    </mappers>
</configuration>
pom.xml中所需坐标:
    <!--  坐标  -->
    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.13</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

 

Account类:
package com.czxy.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
    private Integer id; // 编号
    private String name; // 账户名
    private Integer money; // 金额
}
AccountMapper接口:
package com.czxy.mapper;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

public interface AccountMapper {
    /*
    * 收款
    * */
    @Update("update account set money = money + #{money} where name = #{name}")
    public void in(@Param("money") Integer money, @Param("name") String name);

    /*
    * 汇款
    * */
    @Update("update account set money = money - #{money} where name = #{name}")
    public void out(@Param("money") Integer money, @Param("name") String name);
}
 MybatisUtils类:
package com.czxy.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class MybatisUtils {
    private static SqlSessionFactory sessionFactory;

    static {
        try{
            // 1. 获取核心文件
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            // 2. 获取会话
            sessionFactory = new SqlSessionFactoryBuilder().build(is);
        }catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 获取session
    public static SqlSession getSession() {
        SqlSession session = sessionFactory.openSession();

        return session;
    }

    // 释放资源
    public static void close(SqlSession session) {
        if(session != null) {
            // 提交
            session.commit();
            // 释放
            session.close();
        }
    }
}
 TestAccount类:
import com.czxy.mapper.AccountMapper;
import com.czxy.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class TestAccount {
    @Test
    public void testTruncate() {
        // 获取session
        SqlSession session = MybatisUtils.getSession();

        try{
            // 通过session获取映射
            AccountMapper mapper = session.getMapper(AccountMapper.class);

            // 转入
            mapper.in(50,"rose");
            // 转出
            mapper.out(50,"jack");

            // 提交事务
            session.commit();

            System.out.println("转账成功!");
        }catch (Exception e) {
            // 回退
            session.rollback();
            System.out.println("转账失败!");
        }finally {
            // 释放
            MybatisUtils.close(session);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值