一、关于java中的事务(开启事务、事务的隔离级别、事务的传播性)的总结

一、背景

1.最近在研究java的事务传播性,一直有个地方不太明白的地方,直到在在项目中有看到实际中怎么用到的,才恍然大悟,于是就搜了搜关于java中的事务何时开启,以什么方式开启的,事务的隔离级别以及事务的传播性,于是写下了这个博客来记录下自己的学习成果。

2.也参考了很多大佬的博客文章,最后会把参考的文献提供出来,以供大家参考和学习。如果那里做的不好,欢迎大家留言以及批评指正,废话不多说了,开始上干货。

二、关于如何开启事务

1.Spring的事务管理分为两类:

1.1.编程式事务管理(手动编写代码完成事务管理)

1.2.声明式事务管理(不需要手动编写代码,需要配置)

2.案例一(不加事务的时候)

2.1.创建表

 CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  `money` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

2.2.创建项目并引入Maven依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency> 
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>   
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
    
    <!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
    <!-- Spring 整合测试的包 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>

2.3.项目结构如下:

2.4.编写实体类

public class Account {
    private Integer id;
    private String name;
    private Integer money;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getMoney() {
        return money;
    }
    public void setMoney(Integer money) {
        this.money = money;
    }
    @Override
    public String toString() {
        return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
    }
}

2.5.编写Dao层

/**
 * 银行账户的相关操作 此处用了@see注释,在实现类可以继承接口中方法的注释内容
 * 
 * @author hao
 * @see AccountDaoImpl
 * 
 */
public interface IAccountDao {

    /**
     * 添加账户
     * 
     * @param account 要添加的账户
     */
    public void add(Account account);

    /**
     * 转出的方法
     * 
     * @param from  :转出的账户,打出钱
     * @param money :要转账金额
     */
    public void out(Account from, Integer money);
    
    /**
     * 转出的方法
     * 
     * @param to    转入的账户,收到钱
     * @param money 要转账金额
     */
    public void in(Account to, Integer money);
    
    /**
     * 通过名字查询账户
     * @param name 账户名
     * @return
     */
    public Account selectOneByName(String name);
    
}

2.5.1.实现类

public class AccountDaoImpl implements IAccountDao{

    
    @Autowired
    @Qualifier("jdbcTemplate")
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public void add(Account account) {
        String sql = "insert into account values(null,?,?)";
        jdbcTemplate.update(sql,account.getName(),account.getMoney());
    }
    
    
    @Override
    public Account selectOneByName(String name) {
        String sql = "select * from account where name = ?";
        Account account = null;
        try {//这里需要捕获结果集为空时的异常
            account = jdbcTemplate.queryForObject(sql, new RowMapper<Account>() {

                @Override
                public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Account account = new Account();
                    account.setId(rs.getInt("id"));
                    account.setName(rs.getString("name"));
                    account.setMoney(rs.getInt("money"));
                    return account;
                }
                
            }, name);
        } catch (EmptyResultDataAccessException e) {
            e.printStackTrace();
            return null;
        }
        
        return account;
    }
    
    
    public void out(Account from, Integer money) {
        String sql = "update account set money = money-? where name =? ";
        jdbcTemplate.update(sql, money,from.getName());
    }

    public void in(Account to, Integer money) {
        String sql ="update account set money = money+? where name =?";
        jdbcTemplate.update(sql,money,to.getName());
    }
    
}

2.6.业务层

/**
 * 
 * @author hao
 * @see AccountServiceImpl
 */
public interface IAccountService {

    /**
     * 向数据库中添加用户
     * 
     * @param account 要添加的用户对象
     */
    public void addAccount(Account account);

    /**
     * 转账的方法
     * 
     * @param from  转出的账户
     * @param to    转入的账户
     * @param money 转账金额
     */
    public void transfer(Account from, Account to, Integer money);
    
    /**
     * 
     * @param name 需要查询的账户名
     * @return
     */
    public Account findAccountByName(String name);
}

2.6.1.实现类

/**
 * 没有添加事务
 * @author hao
 *
 */
public class AccountServiceImpl implements IAccountService {
    // 注入 accountDao 利用setter方法注入属性
    private IAccountDao accountDao;

    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void addAccount(Account account) {
        accountDao.add(account);
    }
    
    @Override
    public Account findAccountByName(String name) {
        Account account = accountDao.selectOneByName(name);
        return account;
    }


    @Override
    public void transfer(Account from, Account to, Integer money) {
        accountDao.out(from, money);// 转出钱
        int i= 1/0 //出现异常时
        accountDao.in(to, money);// 收入钱
    }
}

2.7.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/context http://www.springframework.org/schema/context/spring-context.xsd">
    
    <context:property-placeholder location="classpath:jdbc.properties"/>
    
    <!-- 配置c3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean> 
    
    <!-- 这里需要注入数据源 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 此处声明Dao层类,用注解的方式将jdbcTemplate注入到了accountDao中,也可用其他方式  -->  
    <bean 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值